多线程

206 阅读3分钟

layout: post title: "多线程和高并发" subtitle: " "mutil thread and high concurrent"" date: 2018-10-07 06:00:00 author: "青乡" header-img: "img/post-bg-2015.jpg" catalog: true tags: - multi thread

什么是死锁?死锁是怎么发生的?

1.2个线程
2.2个锁对象

每个线程各自拥有一个锁对象,同时,每个线程还要去获取另外一个锁对象,但是这个锁对象已经被对方线程占有。


写一个死锁的代码?

锁对象1
锁对象2

方法1(){
    synchronized(锁对象1){
        synchronized(锁对象2){
            ...
        }
    }
}


方法2(){
    synchronized(锁对象2){
        synchronized(锁对象1){
            ...
        }
    }
}

为什么会出现数据不同步的情况?

1.因为会使用多线程。 2.多线程会导致数据一致性的问题。

为什么要同步?

解决数据一致性的问题。

进程、线程

1.进程 与线程的关系 包含多个线程。


访问数据 不同进程是不同的地址空间。即不同进程里的数据互相不能访问。

那不同进程如何通信? ?

2.线程 与进程的关系 属于进程。 一个进程一般是一个应用程序,一个应用程序要完成多个任务,就会出现多线程。这是多线程最大的作用。


访问数据 共用同一个进程空间(即内存),所以会导致数据不一致。这是最大的问题。


如何解决数据不一致的问题? 基本上所有的技术都是在解决这个问题。

线程的状态

1.新建 new Thread();

2.在运行 Thread.start();

3.睡眠/阻塞 .sleep();

IO阻塞; //本地数据访问、网络数据访问,都会出现访问数据阻塞,例如,数据量太大,网络不好。

4.再次运行 睡醒了;

IO完毕。

5.结束/死亡 代码运行完毕。

怎么同步

有2种方法, 1.基础 即常用方法。

一般使用同步关键字,同步方法或代码块。

2.提高 jdk 线程池。

jdk 高级并发类。

以上都是属于jdk并发包的内容。


怎么使用?


底层原理?

java并发包

线程池

并发集合和映射

显式锁

优点
1.显式锁
2.可以控制同步粒度

还有优点
1.中断
2.超时

并发原子

参考

1.官方文档 docs.oracle.com/javase/tuto…

1)讲并发的有一本书 很好 看那一本书就够

2)还有一本是jdk 并发包 作者写的

3.再结合google 和 维基百科

happen-before

?

指令重排序

就是多线程的代码没有先后顺序,完全随机。

代码

package gzh.test.multiThread;

/**
 * 启动程序
 * 
 * ---
 * 如何才能乱序输出?
 * 调试的时候,在线程1打断点,就会先执行线程2的任务。
 * @author gongzhihao
 *
 */
public class MultiThreadTest {
	static Data d = new Data();

	public static void main(String[] args) {	
		//初始数据
		System.out.println("a=" + d.a + ", flag=" + d.flag);
		System.out.println();
		
		//多线程访问数据
//		for (int i = 0; i < 10; i++) {
//			Thread t1 = new Thread(new TaskThread1());
//			t1.start();
//		}
		
		Thread t1 = new Thread(new TaskThread1());
		t1.start();
		
		Thread t2 = new Thread(new TaskThread2());
		t2.start();
	}

}

package gzh.test.multiThread;

/**
 * 任务线程
 * @author gongzhihao
 *
 */
public class TaskThread1 implements Runnable{
	public void run() {
		System.out.println("current thread: " + Thread.currentThread() + ", MultiThreadTest.d: " + MultiThreadTest.d);
		MultiThreadTest.d.writer();
	}

}

package gzh.test.multiThread;

/**
 * 任务线程
 * @author gongzhihao
 *
 */
public class TaskThread2 implements Runnable{
	public void run() {
		System.out.println("current thread: " + Thread.currentThread() + ", MultiThreadTest.d: " + MultiThreadTest.d);
		MultiThreadTest.d.reader();
	}

}

package gzh.test.multiThread;

/**
 * 数据
 * @author gongzhihao
 *
 */
class Data {
	int a = 0;
	boolean flag = false;

	public synchronized void writer() {
		a = 1;
		System.out.println("a=" + a);
		flag = true;
		System.out.println("flag=" + flag);
	}

	public synchronized void reader() {
		System.out.println("flag=" + flag);
		if (flag) {
			System.out.println("flag=" + flag);
			int i = a;
			System.out.println("i=" + i);
		}
	}
}

输出结果
a=0, flag=false

current thread: Thread[Thread-0,5,main], MultiThreadTest.d: gzh.test.multiThread.Data@67565b6a //看共享数据id,可以看出来是同一个对象67565b6a
current thread: Thread[Thread-1,5,main], MultiThreadTest.d: gzh.test.multiThread.Data@67565b6a
flag=false
a=1
flag=true

线程组ThreadGroup

作用是方便统一管理线程,以及线程的各个特性。

每个线程都属于一个线程组,还有一个父线程组。