官方说明说







来自here

这是否意味着对 volatile 变量的任何写入都会使正在执行的线程将其缓存刷新到主存储器中,而从 volatile 字段中进行的每次读取都会使线程从主存储器中重新读取其变量?

我问是因为相同的文本包含了这一说法



这句话使我非常困惑。我肯定知道使用同步语句进行常规锁获取和释放不是正确的-如果某个线程释放了任何监视器,则它对所有其他线程所做的所有更改都将变为对其他所有线程可见(更新:实际上不正确-观看最佳答案)。在stackoverflow上甚至还有一个question about it。但据指出,无论出于何种原因,对于可变字段而言,情况并非如此。我无法想象在保证之前发生的任何实现,该实现不会使更改对其他线程(不读取相同的volatile变量的线程)可见。至少可以想象一个实现,它与前两个引号没有矛盾。

此外,在发布此问题之前,我进行了一些研究,例如this article,其中包含此句子



提到的指令是在写入 volatile 字段时发生的指令。

那么,该重要说明应该是什么意思?还是我想念什么?也许那条纸条是完全错误的?

回答?

经过更多研究之后,我只能在有关 volatile 字段及其对非 volatile 字段更改的影响的官方文档中找到以下声明:



来自here

我不知道这是否足以得出结论,只有在读取相同volatile的线程中才能保证这种事前发生的关系。因此,到目前为止,我只能总结一下结果尚无定论。

但是在实践中,我建议考虑线程A写入易失字段时所做的更改,只有在线程B读取相同的volatile字段时,才能保证对线程B可见。以上来自官方消息的引用强烈暗示了这一点。

最佳答案

您正在从完全错误的角度看待这个问题。首先,您引用的是JLS,而不是谈论冲洗,这将是该规范的实现细节。您需要依靠的绝对唯一的东西就是JLS,可能还不知道其他任何东西,但是并不能证明任何形式或形式的规范是对还是错。

错误的根本原因是:



实际上,在x86上,您可能是正确的,但是JLS and the official oracle tutorial mandates that:



后继的操作(如果需要,请阅读两个操作,如果您更简单)建立了Happens-before。一个线程释放该锁,另一个线程获取它-这些是后续的(release-acquire semantics)。
volatile也会发生相同的事情-一些线程对此进行写操作,而当其他某个线程通过后续读取观察到该写操作时,则建立before-before。

09-30 17:31
查看更多