java 同步重新排序

Synchronized reordering in java

众所周知,JVM 不应将同步块中的语句重新排序到同步块之外。考虑到这一点,是否允许 JVM 重新排序分配 y = 7 以在以下代码段中的 synchronized 块之后发生?

x = 5;
y = 7;
synchronized (this) {
    x = 6;
}

我们知道同步块之前的变量赋值可以重新排序以发生在块内。因此,以下应该是初始代码的有效重新排序:

x = 5;
synchronized (this) {
    x = 6;
    y = 7;
}

有人可能会争辩说,因为这是一个有效的顺序,所以 y 赋值不能发生在 synchronized 块之后,因为它违反了同步块中的代码不得重新排序的规则发生在块之后并推断 y 发生在同步块的结束 之前。

另一方面,可能不是所有的排序都是等价的,重要的是哪个排序是实际排序。具体来说,如果 y 分配最初是在同步块内完成的,则它不能在块之后发生,否则它可以。

综上所述,第一个片段的下一个排序是否有效?

x = 5;
synchronized (this) {
    x = 6;
}
y = 7;

是的,你的推理有问题;这不可能发生。

监视器输入就像 volatile load(不完全正确,但我理解它更简单 - 将插入两个障碍:LoadLoad|LoadStore)和操作 before 不能漂浮穿过那个障碍。

我很确定,这是由 JLS 指定的,虽然我想 link 到那个,但另一个答案已经做了 - 去投票吧。

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).

...

  • If an action x synchronizes-with a following action y, then we also have hb(x, y).

只有在假设 y 的值在当前线程外可见时,您的问题才有意义。如果是这种情况,这两个规则的组合要求在同步块之后不重新排序赋值。