gpt4 book ai didi

Java volatile 重排序预防作用域

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

写入和读取 volatile 字段分别防止在 volatile 字段之前和之后读取/写入的重新排序。写入 volatile 变量之前的变量读/写不能被重新排序为在它之后发生,并且在从 volatile 变量读取之后的读/写不能被重新排序为发生在它之前。但是这个禁令的范围是什么?据我了解,volatile 变量只能在使用它的 block 内防止重新排序,对吗?

为了清楚起见,让我举一个具体的例子。假设我们有这样的代码:

int i,j,k;
volatile int l;
boolean flag = true;

void someMethod() {
int i = 1;
if (flag) {
j = 2;
}
if (flag) {
k = 3;
l = 4;
}
}

显然,写入 l 会阻止写入 k 的重新排序,但它会阻止写入 i 的重新排序吗j 相对于 l?换句话说,可以在写入 l 之后写入 ij 吗?

更新 1

感谢大家花时间回答我的问题 - 我很感激。问题是你回答错了问题。我的问题是关于范围,而不是关于基本概念。问题基本上是编译器在代码中保证与 volatile 字段的“发生在之前”关系到什么程度。显然,编译器可以保证在同一个代码块内,但是封闭 block 和对等 block 又如何——这就是我的问题所在。 @Stephen C 说,volatile 保证发生在整个方法体内的行为之前,即使在封闭 block 中也是如此,但我找不到任何证实。他是对的吗,有什么地方可以确认吗?

让我再举一个关于范围界定的具体例子来澄清事情:

setVolatile() {
l = 5;
}

callTheSet() {
i = 6;
setVolatile();
}

在这种情况下,编译器会禁止对 i write 重新排序吗?或者也许编译器不能/没有被编程为在易变的情况下跟踪其他方法中发生的事情,并且 i 写入可以重新排序以发生在 setVolatile() 之前?或者编译器可能根本不重新排序方法调用?

我的意思是在某个地方一定有一点,编译器将无法跟踪某些代码是否应该在某些 volatile 字段写入之前发生。否则,一个 volatile 字段的写入/读取可能会影响一半程序的顺序,如果不是更多的话。这种情况很少见,但有可能。

此外,看看这句话

Under the new memory model, it is still true that volatile variables cannot be reordered with each other. The difference is that it is now no longer so easy to reorder normal field accesses around them.

“在他们周围”。这句话暗示,volatile 字段可以在一定范围内阻止重新排序。

最佳答案

Obviously, write to l will prevent write to k from reordering, but will it prevent reordering of writes to i and j?

重新排序的意思并不完全清楚;看我上面的评论。

但是,在 Java 5+ 内存模型中,我们可以说对 ij 的写入发生在对 l 的写入之前> 在读取 l 后将对另一个线程可见 ... 假设在写入 l 后没有写入 ij

这确实具有限制写入 ij 的指令的任何重新排序的效果。具体来说,在写入 l 之后,它们不能移动到内存写入屏障之后,因为这可能导致它们对第二个线程不可见。

But what is the scope of this prohibition?

没有禁令本身

您需要了解指令、重新排序和内存屏障只是实现 Java 内存模型的特定方式的细节。该模型实际上根据保证在任何“格式良好的执行”中可见的内容来定义。

As I understand volatile prevents reordering inside the block where it is used, am I right?

实际上,没有。这些 block 不在考虑之列。重要的是方法中语句的(程序源代码)顺序。


@Stephen C said, that volatile guarantees happen before behavior inside the whole method's body, even in the enclosing block, but I can not find any confirmation to that.

确认为JLS 17.4.3 .它声明如下:

Among all the inter-thread actions performed by each thread t, the program order of t is a total order that reflects the order in which these actions would be performed according to the intra-thread semantics of t.

A set of actions is sequentially consistent if all actions occur in a total order (the execution order) that is consistent with program order, and furthermore, each read r of a variable v sees the value written by the write w to v such that:

  • w comes before r in the execution order, and

  • there is no other write w' such that w comes before w' and w' comes before r in the execution order.

Sequential consistency is a very strong guarantee that is made about visibility and ordering in an execution of a program. Within a sequentially consistent execution, there is a total order over all individual actions (such as reads and writes) which is consistent with the order of the program, and each individual action is atomic and is immediately visible to every thread.

If a program has no data races, then all executions of the program will appear to be sequentially consistent.

请注意,此定义中没有提及 block 或范围。

关于Java volatile 重排序预防作用域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51647337/

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