Java内存模型 (Java Memory Model,简称JMM)
Java内存模型,是Java虚拟机定义的用来屏蔽各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的内存访问效果的一种模型。
Java内存模型规定:
1. 所有的变量都存储在主内存中;
2. 每个线程有自己的工作内存,保顿了被该线程使用的变量的主内存副本拷贝;
3. 线程对变量的所有操作,都只能在工作内存中进行,而不能直接读写主内存中的变量;
4. 不同线程之间无法直接访问对方的工作内存中的变量,线程间变量值的传递只能通过主内存来完成;
Volatile关键字
使用Volatile定义的变量具有和普通变量不同的特殊访问规则:
1. 确保可见性:任何一个线程对Volatile变量的改变,其新值对其他线程立即可见(实际上是每个线程访问volatile变量前要立即刷新该变量的值);
2. 禁止指令重排优化:确保变量赋值操作的顺序与程序代码一致(普通变量只保证依赖变量赋值的地方能够获取到正确的结果,但是有可能优化器会改变两个不相关的变量赋值语句的执行顺序)
注意:
volatile关键字解决了变量在不同线程中的不一致性问题,但是并不意味着对于该变量的运算就是线程安全的了,因为Java的运算并不是原子操作。
volatile屏蔽指令重排的语义子JDK1.5中才被修复,在此之前是存在问题的,所以导致JDK1.5之前无法安全的使用双锁检测(DCL)来实现单例模式。
先行发生原则(happens-before)
先行发生,是Java内存模型定义的两项操作之间的偏序关系。如果说A操作先行发生于B操作,那么在发生B操作之前,A操作产生的影响能被B操作观察到。
先行发生和两个操作时间上的先后并无直接关系,时间上先进行的操作,并不一定是先行发生的;
反过来,先行发生的操作,在时间上也不一定是先进行的(比如发生指令重排的情况)