什么是volatile
关键字volatile 提供了Java 虚拟机中最轻量级的同步机制。在meidium 中有篇文章说:Volatile specifier is used to indicate that a variable’s value can be modified by multiple threads simultaneously
当你使用了volatile之后,那么这个变量会有如下的特性:
保证此变量对所有的线程的可见性
禁止指令重排序优化
对于第一条的内容,volatile是如何保证读写操作对所有的线程可见?
这里涉及到可见性的问题。
对于普通的变量来说,每个线程要想修改变量的值,首先从主存(JMM的定义,在JVM中,大致是可以对应到堆内存的)中拷贝值到自己所属的CPU cache中去。现在的处理器,一般是会有多个CPU的,每个线程可能运行在不同的CPU, 那么线程修改完成的值,是首先保存在CPU cache中去。此时其他的线程是察觉不到修改的结果的,这就造成了并发模型中的可见性问题。
考虑这样一种情况:
public class SharedObject {
public int counter = 0;
}
现在有两个线程, 线程1和线程2, 他们不时会去读取这个共享变量。如果counter没有声明volatile这个关键字,那么此时就无法保证counter的值何时从CPU缓存写回到主存。这意味着,counter在CPU cache中的值和主存中的会不一致。
但是如果声明了volatile的话,对volatile变量进行写操作的话,那么JVM就会向处理器发送一条LOCK前缀的指令,将这个变量所在缓存行中的数据写回到系统内存。
写回的过程,为了保证各个处理器的缓存是一一致的,就会实现缓存一致性协议。
缓存不停地窥探总线上发生的数据交换,来检查自己的数据是不是已经过期了。如果发现此时缓存行中的值已经失效的话,就会将当前缓存行中的值设置为无效状态。处理器要用到这个值的话,就会从内存中重新获取这个值。
禁止指令重排序
指令重排序是指CPU采用了允许将多条指令不按照程序规定的顺序分开发送给各相应的电路单元处理
TODO --