简体   繁体   English

java中的同步重新排序

[英]Synchronized reordering in java

It is known that JVM shouldn't reorder statements from withing synchronized block to outside of the synchronized block. 众所周知,JVM不应该将带有同步块的语句重新排序到同步块之外。 Considering this, is JVM allowed to reorder assignment y = 7 to occur after the synchronized block in the following snippet? 考虑到这一点,是否允许JVM重新排序赋值y = 7以在以下代码段中的synchronized块之后发生?

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

We know that variable assignment before the synchronized block can be reordered to occur inside the block. 我们知道在同步块之前的变量赋值可以重新排序以在块内发生。 So the following should be valid reordering of the initial code: 所以以下内容应该是初始代码的有效重新排序:

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

One could argue that, because this is a valid ordering, y assignment cannot occur after the synchronized block as it would violate the rule that code from within synchronized block mustn't be reordered to occur after the block and deduce that y happens-before end of the synchronized block. 有人可能会争辩说,因为这是一个有效的排序,所以在synchronized块之后不能进行y赋值,因为它会违反规则,即在块之后不得重新排序来自同步块内的代码并推断出y 发生在结束之前同步块的。

On the other hand, it could be that all orderings are not equivalent and it matters which ordering was the actual ordering. 另一方面,可能所有的排序都不等同,而且排序是实际的排序也很重要。 Specifically, if y assignment was originally done within the synchronized block it couldn't occur after the block, otherwise it could. 具体来说,如果y赋值最初是在同步块内完成的,则在块之后不会发生,否则就可能发生。

To sum up, is next ordering valid ordering of the first snippet? 总结一下,接下来是订购第一个片段的有效排序吗?

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

JLS 17.4.5 : 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). 如果x和y是同一个线程的动作,并且x在程序顺序中出现在y之前,那么hb(x,y)。

... ...

  • If an action x synchronizes-with a following action y, then we also have hb(x, y). 如果动作x与后续动作y同步,那么我们也有hb(x,y)。

Your question only makes sense when including the assumption that the value of y could be visible outside the current thread. 只有在假设y的值在当前线程之外可见时,您的问题才有意义。 If that's the case, the combination of these two rules requires that the assignment not be reordered after the synchronized block. 如果是这种情况,则这两个规则的组合要求在同步块之后不重新分配赋值。

Yes, your reasoning are flawed; 是的,你的推理存在缺陷; this can not happen. 这不可能发生。

A monitor enter is like a volatile load (not entirely correct, but I understand it simpler like that - there will be two barriers inserted : LoadLoad|LoadStore ) and operations that are before that can not float across that barrier. 监视器输入就像一个volatile load (不完全正确,但我理解它更简单 - 插入两个障碍: LoadLoad|LoadStore )和之前的操作不能跨越该障碍。

I am pretty sure, this is specified by the JLS and while I wanted to link to that, the other answer has already did - go upvote it. 我很确定,这是由JLS指定的,虽然我想链接到那个,但另一个答案已经做了 - 去投票吧。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM