gpt4 book ai didi

java - volatile 的发生之前和重新排序

转载 作者:搜寻专家 更新时间:2023-11-01 03:31:13 24 4
gpt4 key购买 nike

有多个代码示例假定以下指令 (1)(2) 不能重新排序:

int value;
volatile boolean ready;

// ...

value = 1; // (1)
ready = true; // (2)

后面的Stack Overflow答案引用了JLS §17.4.5 :

If x and y are actions of the same thread and x comes before y in program order, then hb(x, y).

但是我不明白为什么这应该适用于此,因为 JLS Example 17.4-1还指出:

[...] compilers are allowed to reorder the instructions in either thread, when this does not affect the execution of that thread in isolation.

这里显然是这种情况。

JLS 中特定于 volatile 的所有其他定义仅针对相同的 volatile 变量,而不针对其他操作:

A write to a volatile field (§8.3.1.4) happens-before every subsequent read of that field.


让我感到困惑的是人们看到保证 volatile(读或写)的使用可能不会被重新排序。

能否请您根据 JLS 或基于 JLS 的其他来源进行解释。

最佳答案

孤立地,您的代码不能保证任何事情。这里涉及第二个线程,我们也需要它的代码!您链接的教程显示两个线程是有原因的。

如果两个线程的代码是这样的:

int value;
volatile boolean ready;

// Thread - 1
value = 1; // (1)
ready = true; // (2)

// Thread - 2
if (ready) { // (3)
x = value // (4)
}

那么由于程序顺序,我们在 (1) 和 (2) 之间有一个 happens-before 关系:

If x and y are actions of the same thread and x comes before y in program order, then hb(x, y).

由于 ready 是易变的,我们在 (2) 和 (3) 之间有一个先行发生的关系:

A write to a volatile field (§8.3.1.4) happens-before every subsequent read of that field.

由于程序顺序,我们在 (3) 和 (4) 之间有一个先行发生的关系:

If x and y are actions of the same thread and x comes before y in program order, then hb(x, y).

所以有一个 happens-before 链 (1) → (2), (2) → (3), (3) → (4)

并且由于 happens-before 是一个传递关系(如果 A 发生在 B 之前并且 B 发生在 C 之前,那么 A 发生在 C 之前)这意味着 (1) 发生在 (4) 之前。

如果我们翻转 (3) 和 (4) 以便第二个线程在读取 ready 之前读取 value,那么 happens-before 链中断,我们不再从 value 中获取有关读取的任何保证。

这是一个不错的 tutorial还有一些 JMM 陷阱,包括这个。

Java内存模型是不是很好玩?

关于java - volatile 的发生之前和重新排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54081251/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com