共计 989 个字符,预计需要花费 3 分钟才能阅读完成。
什么是 volatile
关键字 volatile 提供了 Java 虚拟机中最轻量级的同步机制。在 meidium 中有篇文章说:Volatile specifier is used to indicate that a variable’s value can be modified by multiple threads simultaneously
当你使用了 volatile 之后,那么这个变量会有如下的特性:
- 保证此变量对所有的线程的可见性
- 禁止指令重排序优化
对于第一条的内容,volatile 是如何保证读写操作对所有的线程可见?
这里涉及到可见性的问题。
对于普通的变量来说,每个线程要想修改变量的值,首先从主存 (Main Mermory, 也就是我们通常所说的) 中拷贝值到自己所属的 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 采用了允许将多条指令不按照程序规定的顺序分开发送给各相应的电路单元处理
参考:
- https://blog.usejournal.com/j…
- https://medium.com/@siddhusin…
- https://www.cnblogs.com/dolph…
- 《Java 特种兵》