volatile关键字
- 保证可见性
- 禁止指令的重排序
volatile有啥用??
看下面的代码会输出什么呢
1 | public class VolatileTest{ |
答案一:[ main ===> true
然后阻塞。。。。。。。。。。。。。。。 ]
分析:有两个线程main和一个子线程,可以发现两线程存在一个共享的变量flag,当主线程修改flag为true之后会输出
main ===> true,但是程序并没有结束,而是在子线程中陷入了阻塞。因为子线程中flag的值仍然为False,为什么会这样??原来这是因为java内存模型决定的。每个线程都会自己的工作内存,其中会保存主内存中共享变量的一份拷贝,修改完之后在刷新到主内存中。然而上面那段代码中子线程工作内存得到的是false,导致了while(true)死循环。
修改方法:直接使用volatile关键字修饰flag变量。volatile会保证变量的可见性。也就是子线程会立刻察觉到flag变量已经改变就不会死循环啦~。
底层原理
- 如何保证可见性:对volatile关键字修饰的变量进行写操作的指令 前面添加lock前缀,那么这条指令就会将修改完的数据从缓存中刷新到主内存中,同时令其他CPU缓存中的这个缓存失效。这样在其他线下次需要使用到这个变量的时候就会重新从主内存中读取到缓存中,也就得到了最新的修改值,从而保证了变量的可见性。(这条lock前缀指令其实就是利用了缓存一致性协议,保证每个CPU核中的缓存值一致)
- 如何禁止指令重排序: