2

我现在正在阅读 Java 语言规范。

§17.4.5-1

在此执行中,读取会看到执行顺序后面发生的写入。这可能看起来违反直觉,但在发生之前的一致性允许。允许读取看到稍后的写入有时会产生不可接受的行为。

§17.4.8-1

尽管有时不希望允许读取看到执行顺序后面的写入,但有时也是必要的。

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必须发生在最后。

4

1 回答 1

2

这个例子

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 代码不允许这种情况。这是一个允许的例子,如果我们只有发生前的一致性。但 Java 也禁止“凭空产生价值”。因此,支持这种推测执行的架构的 JVM 实现必须确保它仅限于其他线程看不到的变量(或完全禁用它)。

于 2018-08-13T15:57:57.293 回答