对 volatile 字段的写入和读取分别防止在 volatile 字段之前和之后重新排序读/写。写入 volatile 变量之前的变量读/写不能重新排序在它之后发生,而从 volatile 变量读取之后的读/写不能重新排序在它之前发生。但这项禁令的范围是什么?据我了解, volatile 变量只能防止在使用它的块内重新排序,对吗?
为了清楚起见,让我举一个具体的例子。假设我们有这样的代码:
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;
}
}
显然,write tol将阻止 write tok重新排序,但它会阻止重新排序写入i和j关于l? 换句话说,可以写入i并j在写入之后发生l吗?
更新 1
感谢大家花时间回答我的问题 - 我很感激。问题是你回答了错误的问题。我的问题是关于范围,而不是关于基本概念。问题基本上是编译器在代码中保证“发生在之前”与 volatile 字段的关系有多远。显然编译器可以保证在同一个代码块内,但是封闭块和对等块呢 - 这就是我的问题。@Stephen C 说,volatile 保证发生在整个方法主体内部的行为之前,即使在封闭块中,但我找不到任何确认。他说得对吗,有什么地方可以确认吗?
让我再举一个关于范围界定的具体例子来澄清事情:
setVolatile() {
l = 5;
}
callTheSet() {
i = 6;
setVolatile();
}
i在这种情况下,编译器会禁止重新排序写入吗?或者编译器不能/没有被编程来跟踪在 volatile 情况下其他方法中发生的事情,并且i可以重新排序写入之前发生setVolatile()?或者编译器根本不重新排序方法调用?
我的意思是在某处必须有一个点,当编译器将无法跟踪某些代码是否应该在某些 volatile 字段写入之前发生时。否则,一个易失性字段写入/读取可能会影响一半程序的排序,如果不是更多的话。这是一种罕见的情况,但它是可能的。
此外,看看这个报价
在新的内存模型下,volatile 变量不能相互重新排序仍然是正确的。不同之处在于现在不再那么容易对它们周围的正常字段访问重新排序。
“在他们旁边”。这句话暗示,有一个范围,其中 volatile 字段可以防止重新排序。
互换的青春
catspeake
相关分类