volatile的定义与原理

一.定义

java语言规范第三版对volatile的定义如下:

java编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致的更新,线程应该确保通过排他锁单独获得这个变量。

java语言提供了volatile,在某些情况下比锁更加方便,如果一个字段被声明称volatile,java线程内存模型能够确保所有线程看到这个变量的值是一致的。

二. volatile如何保证可见性

我们在x86 处理器下通过工具获取jit编译器生成的汇编指令来查看volatile进行写操作时,CPU会做什么?

java代码如下:

instance= new Singleton();  // instance 是volatile 变量

转换成汇编代码,会有个Lock 前缀的指令。

Lock前缀的指令会引发两件事情

1.将当前处理器缓存行的数据写回到系统内存。

2.这个写回内存的操作会使在其他CPU里缓存了该内存地址的数据无效。

为了提高处理器速度,处理器不直接与内存进行通信,而是先将系统内存的数据读到内部缓存(L1,L2 )后再进行操作,但是操作完后不知道什么时候会写到内存中。如果对声明了volatile的变量进行写操作,jvm会向处理器发送一条Lock前缀的指令,将这个变量所在的缓存行数据写回到系统内存。但是,就算是写回到内存中,还存在一个问题,就是如果其他处理器缓存的值还是旧值,再执行计算操作就会有问题。所以在多处理器下,为了保证各个处理器的缓存是一致的,就会实现缓存一致性协议,每个处理器通过嗅探在总线上传播的数据来检查自己的缓存值是不是过期了,当处理器发现自己缓存行对应的内存地址被修改,就会将缓存行设置成无效状态,当处理器对这个数据进行操作的时候,会重新从系统内存中把数据读到处理器缓存中。

volatile两条实现原则:

1.Lock前缀的指令会引起处理器缓存写回到内存。

2.一个处理器的缓存回写到内存会导致其他处理器的缓存无效。

参考:《java并发编程的艺术》

猜你喜欢

转载自blog.csdn.net/yuanshangshenghuo/article/details/99886992