特性
- 可以保证不同线程对共享变量的可见性
- 可以禁止指令重排(有序性)
- 对于复合操作不可以保证原子性
可见性
指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。指令重排
见:指令重排内存语义
- volatile写的内存语义: 当写一个volatile变量时,JMM会把该线程对应的本地内存中的所有共享变量值刷新到主内存
volatile读的内存语义:当读一个volatile变量时,JMM会把该线程对应的本地内存置为无效。线程接下来将从主内存中读取所有共享变量。
内存语义的实现——内存屏障指令(即如何实现可见性和有序性?)
java 编译器在生成指令序列的适当位置会插入内存屏障指令内存屏障(Memory Barrier)来禁止特定类 型的处理器重排序,从而让程序按我们预想的流程去执行。
写操作:在其前后分别加上 StoreStore 和 StoreLoad指令
- 读操作:在其后加上 LoadLoad 和 LoadStore指令
通俗的理解:
- volatile写,分别通过storestore(防止和之前的写重排),stroeload(防止和之后的读重排)
- volatile读,分别通过loadload(防止和之后的读重排),loadstore(防止和之后的写重排)
由此可看到:
- 内存屏障是可以保证volatile变量前后读写顺序的(可保证有序性);
- 写操作时,使用store指令会强制线程刷新数据到主内存,读操作使用load指令会强制从主内存读取变量值(保证可见性)。