这样,这个操作就会使得:1. 立即将该处理器缓存(具体说是缓存行)中的数据刷新到内存。2. 使得其他处理器缓存(具体说是缓存了该内存地址的缓存行)失效。第一步将缓存刷新到内存后,使得其他处理器缓存失效,也就是第二步的发生,是利用了 CPU 的缓存一致性协议。而为了实现缓存一致性协议,每个处理器通常的一个做法是,通过监听在总线上传播的数据来判断自己的缓存值是否过期,这种方式叫总线嗅探机制。总之,这两个效果一出,在程序员或者线程的眼中,就变成了可见性的保证。
根据 JMM 向程序员提供的抽象模型,我们可以推测出如下问题。此时线程 2 并没有读到线程 1 写入的最新值,a=2,而是读到了主内存中的旧值,a=1。 也即,线程 1 对共享变量的写入,对线程 2 不可见。那么在 Java 中,如何让一个共享变量具有上述的可见性呢?答案是加一个 volatile 即可。在 jls 里是这样描述 volatile 的。The Java programming language allows threads to access shared variables. As a rule, to ensure that shared variables are consistently and reliably updated, a thread should ensure that it has exclusive use of such variables by obtaining a lock that, conventionally, enforces mutual exclusion for those shared variables.The Java programming language provides a second mechanism, volatile fields, that is more convenient than locking for some purposes.简单说,Java 语言为了确保共享变量得到一致和可靠的更新,可以通过锁,也可以通过更轻量的 volatile 关键字。比如在一个变量 a 前面加上了 volatile 关键字