【综述】
Java内存模型详细地描述了Java中多线程之间如何通过共享内存进行通信的。
首先,抽象地定义了多线程和主内存之间的关系。
接着,抽象地定义了共享变量被线程读写操作间的偏序关系,即happens-before规则。
最后,Java内存模型解决了共享变量被多线程操作的可见性问题。
【主内存和本地内存】
这里抽象地给出线程和主内存间的关系定义:
多个线程间的共享变量存储在主内存;
每个线程都有一个本地内存,本地内存中保存的是被所属线程读写的共享变量的拷贝;
线程对变量的操作都必须在本地内存中进行,而不能直接读写主内存中的共享变量;
其中,本地内存是对高速缓存、寄存器、缓冲区、编译器优化等软硬件机制的抽象。
【happens-before规则】
happens-before规则抽象地定义了多线程对共享变量的读写操作的偏序关系,实际上就是定义了在什么条件下一个线程对于共享变量的写操作对另一个线程可见。
An unlock on a monitor happens-before every subsequent lock on that monitor. (同步锁和显式锁的可见性)
A write to a volatile field happens-before every subsequent read of that field. (volatile共享变量的可见性)
A call to start() on a thread happens-before any actions in the started thread. (start方法的可见性)
All actions in a thread happen-before any other thread successfully returns from a join() on that thread. (join方法的可见性)
The default initialization of any object happens-before any other actions (other than default-writes) of a program. (对象初始化方法的可见性)
程序次序规则:在单线程中,按照代码的执行顺序,(时间上)先执行的操作happen—before(时间上)后执行的操作
传递性:如果操作A happen—before操作B,操作B happen—before操作C,那么可以得出A happen—before操作C
线程中断规则:对线程interrupt()方法的调用happen—before发生于被中断线程的代码检测到中断时事件的发生。
【案例分析】
注意仔细体会使用较少的volatile(同步锁、显式锁)、较多的跟volatile无关的happens-before规则来保证共享变量操作的可见性
案例1 DCL单例模式中的线程安全问题
试着应用happens-before法则分析,见 http://blog.csdn.net/ns_code/article/details/17359719
案例2 只使用一个volatile变量,就可以保证普通共享变量和其的可见性
见 http://blog.csdn.net/htq__/article/details/51764156