三大特性:1.保证可见性 2.不保证原子性 3.防止指令重排
保证可见性原理
在volatile中是采用锁总线的方式实现可见性,在总线被锁期间其他CPU不可以访问主内存中变量,这种方式效率太低。
现在的可见性是由java和CPU共同完成的,利用CPU的缓存一致性来保证可见,原理如下:
M
要想理解可见性原理首先得知道JMM的8个原子操作,如下图所示红色字体
- 首先线程B修改了flag的值,并传递给工作内存
- 工作内存将flag标记为M(Modify)状态,并发送一个消息给总线
- A将会通过总线嗅探机制发现变量修改消息,此时A中的flag将会被置为无效状态 I(invalid)
- A重新读取主内存中的变量,以达到同步。
变量状态
不保证原子性的原因
在上图中,当线程B修改了变量值后线程A中的就失效了,也就是说,不论A中执行器对变量做了什么操作都会被视为无效,而重新从主存中读取变量值,也就是说A的操作不是原子性操作。
防止指令重排
指令重排是指在程序执行过程中, 为了性能考虑, 编译器和CPU可能会对指令重新排序.
防止指令重排的方式就是加上内存屏障,只要加了volatile的就会在前后加上内存屏障