java内存模型中,每个线程有自己的工作内存,同时还有一个共享的主内存。
为什么要让每个线程都有自己的工作内存呢?
线程运行的代码对应的是一些指令是由CPU执行的!但是CPU每次执行指令运算的时候,要是每次需要一个变量的值,都从主内存加载,性能会比较差!
java同步的八种操作:
1.lock(锁定):主内存中,把一个变量标识为一个线程独占的状态
2.unlock(解锁):主内存中,把一个处于锁定状态的变量释放出来
3.read(读取):主内存中,把一个变量从主内存传输到线程的工作内存
4.load(加载):工作内存中,把read操作的从主存中大袋的变量放入工作内存的变量副本中
5.use(使用):工作内存中,把工作内存中的一个变量传递给执行引擎
6.assign(赋值):工作内存中,把一个从执行引擎接收到的值赋给工作内存中的变量
7.store(保存):工作内存中,把工作内存中的变量传送给主内存中,以便进行write的操作
8.write(写入):主内存中,把store操作从工作内存中的变量的值传输到主内存的变量中
Volatile如何保证有序性:
Java内存模型中,允许编译器和处理器对指令进行重排序,但是重排序不会影响单线程程序的执行,却会影响到多线程并发的正确性。
Volatile通过内存屏障,防止重排序
- 在每个volatile写操作的前面插入一个storestore屏障。
- 在每个volatile写操作的后面插入一个storeload屏障。
- 在每个volatile读操作的后面插入一个loadload屏障。
- 在每个volatile读操作的后面插入一个loadstore屏障。
如何保证有序性:Volatile ,Synchronized ,lock
java内存模型具有先天的有序性,不需要通过任何手段得到保证,如何两个操作不能通过happenBefore原则导出来:
happenBefore原则:
1.程序次序规则:一段程序代码,在单个线程当中,看起来是有序的。
2.锁定规则:一个unlock先行于后面的lock操作
3.volatile变量规则:对一个变量的写操作,先行与读操作
4.传递规则:如果A先行与B,B先行于C,则A先行于C
5.线程启动原则:一个线程必须要执行start方法,才能进行其他操作
6.线程中断原则:不许要执行interrupt()方法,才能检测到有终端事件的发生
7.线程终结规则:线程中的所有操作 先行于他的终止检测
8.对象终结原则:一个对象的初始化,先行于 他的 finalize() 方法的开始