Java 规范:读取看到执行顺序中稍后发生的写入

Java Specification: reads see writes that occur later in the execution order

我正在阅读 Java 语言规范。

§17.4.5-1

In this execution, the reads see writes that occur later in the execution order. This may seem counterintuitive, but is allowed by happens-before consistency. Allowing reads to see later writes can sometimes produce unacceptable behaviors.

§17.4.8-1

Although allowing reads to see writes that come later in the execution order is sometimes undesirable, it is also sometimes necessary.

另外17.4.8-1给出了一个奇怪的例子

为什么 reads see writes come later 可能?

如果真的可行,我如何在 java 代码中重现它?

编辑

这不是重复的问题。那个问题刚问了 17.4.5-1,我能理解 17.4.5-1 因为编译器可能会重新排序它们。但是 17.4.8-1 呢?它在 Executions and Causality Requirements 下。根据execution order的定义,没有人可以重新订购

r1 = x; // write

if (r1 != 0) // read

因此 y = 1 必须发生在最后。

例子

Table 17.4.8-A

      Thread 1                  Thread 2
r1 = x;                    r2 = y;
if (r1 != 0) y = 1;        if (r2 != 0) x = 1;

在具有 推测性 执行的架构上是可能的。所以CPU在主存请求的值还没有到达时遇到条件分支,决定执行条件代码,如果条件不满足就回滚。

当值到达CPU核心时,是其他线程写入的值,所以条件满足,变化保持。

您不能在 Java 代码中重现此内容,因为规范继续说明 Java 代码不允许出现这种情况。这是允许的示例,如果我们只有 happens-before 一致性。但是 Java 还禁止“凭空值”。因此,支持此类推测执行的体系结构的 JVM 实现必须确保它仅限于其他线程看不到的变量(或完全禁用它)。