一.目的
减少并发开销。
实现线程可见性,与禁止重排序。
最终解决的问题是:
线程1执行以下逻辑:
初始化资源;//[1]
设置initFlag=true;//[2]
线程2执行以下逻辑:
if(initFlag){[3]
获取初始化后的资源做一些业务操作。//[4]
}
这里如果[1]和[2]或者[3]和[4]发生重排序,或者说[1]操作的数据没有写到内存而initFlag已经变为true。
这时就会发生在执行[4]由于初始化资源操作未完成的一些异常。
volatile可以用来解决这个问题,用的正是可见性与禁止重排序两个特性。
二.适用场景
以下情况不适用:
复合指令,以及当前volatile变量的值更新依赖于上一个值。
eg:变量的自增操作。
更多的情况用于开关,状态变量等。
三.实现原理
底层通过增加内存屏幛来实现。
3.1.volatile写
在volatile变量写操作的前面会插入store-store内存屏幛,来使之前的写操作全部刷新到主存而不会被cpu缓存,并且不会发生上面的普通写操作与volatile写重排序。
在volatile变量写操作的后面插入store-load内存屏幢。防止后面的volatile读写操作与当前volatile写操作重排序。
底层,比如在volatile的写后面会有条lock前缀的cpu指令。这条指令后cpu会强制将volatile变量写及它之前的变量全部写到内存。
3.2.2.volatile读
在volatile读操作后面,会插件load-store内存屏幛,来禁止后面普通写操作与当前volatile重排序。
并且会插入load-load,禁止后面的普通读操作与当前volatile重排序。