
前言
java线程之间的通信由java内存模型控制,java内存模型决定了一个线程对共享变量的修改何时对
另外一个线程可见。线程之间的共享变量存储在主内存中,每个线程都有一个私有的本地内存,它存
储了该共享变量的副本。本地内存是一个抽象概念,它涵盖了缓存、写缓冲区、寄存器以及其他的硬
件和编译器优化。
1、几种类型的内存屏障
为了保证内存可见性,java编译器会在生成指令序列的适当位置插入内存屏障指令来禁止某些处理器
重排序。其中StoreLoad是一个全能型的屏障,同时具有其他三个屏障的效果。
-
LoadLoad Barriers
Load1 LoadLoad Load2 指令之前的指令装载会先于之后指令的装载 -
StoreStore Barriers
Store1 StoreStore Store2 确保Store1数据对其他处理器可见 先于 Store2及后续指令的存储 -
LoadStore Barriers
Load1 LoadStore Store2 确保Load1数据的装载优 先于 Store2的数据刷新到内存 -
StoreLoad Barriers
Store1 StoreLoad Load2 确保Store1数据存储对其他处理器可见 先于 Load2及后续指令的装载
2、happens-before原则
在java内存模型中,如果一个操作执行的结果要对另外一个操作可见,那么这两个操作之间必须要存在
happens-before关系。这种关系并不意味着前一个操作必须要先于后一个操作执行,而是前一个操作
需要对后一个操作可见。它有以下几条原则:
-
程序顺序规则:一个线程中的每个操作,happens-before于该线程的任意后续操作。
-
监视器锁规则:对于一个锁的解锁,happens-before于随后对这个锁的加锁
-
volatile变量传递规则:对一个volatile变量的写,happens-before于后续任意个对这个变量的读
-
传递性:如果A happens-before B,B happens-before C,那么A happens-before C。




近期评论