volatile是如何实现可见性的?
如果一个字段被声明为volatile,Java线程内存模型确保所有线程看到这个变量的值是一致的。
PS:如果你不了解内存模型的话,非常建议先去了解一下Java的内存模型,可以看我的这篇文章:Java的内存模型。
其实被volatile修饰的共享变量在转变成汇编语言后会在执行写操作是增加一个lock指令。
通过查IA-32架构软件开发者手册可知,Lock 前缀的指令在多核处理器下会引发了两件事情。
(这两件事情在IA-32软件开发者架构手册的第三册的多处理器管理章节第8章)
- 将当前处理器缓存行的数据写回到系统内存。
- 这个写回内存的操作会使在其他CPU里缓存了该内存地址的数据无效。
解释第一件事:
如果对声明了volatile的变量进行写操作,JVM就会向处理器发送一条 Lock前缀的指令,将这个变量所在缓存行的数据写回到系统内存。
解释第二件事:
如果其他处理器缓存的值还是旧的,再执行计算操作就会有问题。为了保证各个处理器的缓存是一致的,就会实现缓存一致性协议,每个处理器通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了,当处理器发现自已缓存行对应的内存地址被修改,就会将当前处理器的缓存设置成无效状态,当处理器对这个数据进行修改操作的时候,会重新从系统内存中把数据读到处理器缓存里