Java中的同步重新排序

时间:2018-10-14 20:11:38

标签: java synchronized

众所周知,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;

2 个答案:

答案 0 :(得分:5)

JLS 17.4.5

  
      
  • 如果x和y是同一线程的动作,并且x按程序顺序位于y之前,则hb(x,y)。
  •   
     

...

     
      
  • 如果动作x与后面的动作y同步,那么我们还有hb(x,y)。
  •   

仅当包含y的值在当前线程之外可见的假设时,您的问题才有意义。在这种情况下,这两个规则的结合要求在同步块之后不要重新分配分配。

答案 1 :(得分:0)

是的,您的推理有缺陷;这不可能发生。

监视器回车就像volatile load(不是完全正确,但我理解得更简单,它将插入两个障碍:LoadLoad|LoadStore)和之前的操作不能跨越障碍。

我很确定,这是由JLS指定的,虽然我想链接到该链接,但另一个答案已经完成了-请对其进行投票。