我是否正确理解了 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 的读取之上,因为这不会改变程序的功能。