volatile的作用:
- 可见性
- 防止重排序。
Java语言规范定义:
Java语言允许线程访问共享变量,为了确保共享变量能被准确和一致地更新,线程应该确保通过排他锁单独获得这个变量。
- 排他锁(X锁):线程给A上锁,只允许A读和写,直到释放锁(更删查都不允许)。
- 共享锁(S锁):线程给A上锁,其他线程只能加S锁,不能加X锁(读取)。
在程序运行中,会将运行所需要的数据复制一份到CPU高速缓存中,在进行运算时CPU不再也主存打交道,而是直接从高速缓存中读写数据,只有当运行结束后才会将数据刷新到主存中。
- 通过在总线加LOCK#锁的方式
- 通过缓存一致性(MESI)协议
查看底层代码会发现,带有volatile 的共享变量进行读写操作的时候,底层会多出一个lock代码的指令。
JVM采用的MESI协议,这时候lock指令会发生两件事情:
- 将当前处理器缓存行的数据写回到系统内存。
- 这个写会内存的操作会使其他cpu里缓存了改内存地址的数据无效
上述说明了可见性,接下来我们来看一下有序性。