我是否正确理解了 JSR-133 Cookbook 中的 Can Reorder 规则?
Do I have the correct understanding of Can Reorder rules from the JSR-133 Cookbook?
在这个 link http://gee.cs.oswego.edu/dl/jmm/cookbook.html 中,有一个 table 谈到什么可以重新排序,什么不能。
这是图片
现在看看 http://tutorials.jenkov.com/java-concurrency/volatile.html
中的这句话
"Instructions before and after can be reordered, but the volatile read or write cannot be mixed with these instructions."
例如说我有代码
int x = 5;
int z = 2; // storing 2 into z
z = someVolatileIntNotTwo; // storing some volatile int that != 2 into z
int a = 6;
System.out.println(z);
据 table 告诉我的,它是说正常存储和易变负载可以重新排序,这意味着
int z = 2; // storing 2 into z
z = someVolatileIntNotTwo; // storing some volatile int that != 2 into z
可以重新订购到
z = someVolatileIntNotTwo; // storing some volatile int that != 2 into z
int z = 2; // storing 2 into z
这可能意味着程序将在重新排序的情况下打印 2 以外的内容。
这背后的原因是,首先 z = 2 进行正常存储,然后 z = someVolatileIntNotTwo 进行易失性加载,然后进行正常存储。虽然无法重新排序后跟正常存储的易失性加载是真的,但在这种情况下,这不会发生,因为如果重新排序,我们仍然会得到这个序列。
z = someVolatileIntNotTwo; // volatile Load then normal Store.
int z = 2; // normal load
除了正常加载 (int z = 2) 和 [volatile load and normal store](z = someVolatileIntNotTwo) 根据 table 很好
但是,jenkov 教程说这是不可能的。
那么,谁是对的?
您对重新排序范围的解释过于宽泛。来自 JSR-133 食谱:
even though the table doesn't say so, you can't reorder a load with a subsequent store to the same location.
更直接地回答你的问题:两篇文章都没有错。您样本中的重新排序是非法的。
仅当发出的重新排序保持程序顺序就像单个线程正在执行时,才会发生重新排序。这意味着,JVM 无法通过重新排序来更改应用程序的结果。所以在你的情况下,不,这不是合法的重新排序。
如果我以你为例
int x = 5;
int z = 2; // storing 2 into z
z = someVolatileIntNotTwo; // storing some volatile int that != 2 into z
int a = 6;
System.out.println(z);
有效的重新排序是
int a = 6;
int x = 5;
int z = 2; // storing 2 into z
z = someVolatileIntNotTwo; // storing some volatile int that != 2 into z
System.out.println(z);
将 a
的赋值移动到 someVolatileIntNotTwo
的读取之上,因为这不会改变程序的功能。
在这个 link http://gee.cs.oswego.edu/dl/jmm/cookbook.html 中,有一个 table 谈到什么可以重新排序,什么不能。
这是图片
现在看看 http://tutorials.jenkov.com/java-concurrency/volatile.html
中的这句话"Instructions before and after can be reordered, but the volatile read or write cannot be mixed with these instructions."
例如说我有代码
int x = 5;
int z = 2; // storing 2 into z
z = someVolatileIntNotTwo; // storing some volatile int that != 2 into z
int a = 6;
System.out.println(z);
据 table 告诉我的,它是说正常存储和易变负载可以重新排序,这意味着
int z = 2; // storing 2 into z
z = someVolatileIntNotTwo; // storing some volatile int that != 2 into z
可以重新订购到
z = someVolatileIntNotTwo; // storing some volatile int that != 2 into z
int z = 2; // storing 2 into z
这可能意味着程序将在重新排序的情况下打印 2 以外的内容。
这背后的原因是,首先 z = 2 进行正常存储,然后 z = someVolatileIntNotTwo 进行易失性加载,然后进行正常存储。虽然无法重新排序后跟正常存储的易失性加载是真的,但在这种情况下,这不会发生,因为如果重新排序,我们仍然会得到这个序列。
z = someVolatileIntNotTwo; // volatile Load then normal Store.
int z = 2; // normal load
除了正常加载 (int z = 2) 和 [volatile load and normal store](z = someVolatileIntNotTwo) 根据 table 很好
但是,jenkov 教程说这是不可能的。 那么,谁是对的?
您对重新排序范围的解释过于宽泛。来自 JSR-133 食谱:
even though the table doesn't say so, you can't reorder a load with a subsequent store to the same location.
更直接地回答你的问题:两篇文章都没有错。您样本中的重新排序是非法的。
仅当发出的重新排序保持程序顺序就像单个线程正在执行时,才会发生重新排序。这意味着,JVM 无法通过重新排序来更改应用程序的结果。所以在你的情况下,不,这不是合法的重新排序。
如果我以你为例
int x = 5;
int z = 2; // storing 2 into z
z = someVolatileIntNotTwo; // storing some volatile int that != 2 into z
int a = 6;
System.out.println(z);
有效的重新排序是
int a = 6;
int x = 5;
int z = 2; // storing 2 into z
z = someVolatileIntNotTwo; // storing some volatile int that != 2 into z
System.out.println(z);
将 a
的赋值移动到 someVolatileIntNotTwo
的读取之上,因为这不会改变程序的功能。