是否与边缘编译器同​​步重新排序两个方向的障碍?

时间:2014-11-03 22:27:28

标签: java multithreading compiler-optimization memory-model java-memory-model

我对Java内存模型有疑问。给出以下示例:

action 1
action 2
synchronized(monitorObject) { //acquire
    action 3
} //release
action 4

acquirerelease可以是任何同步边缘(锁定,解锁,启动线程,连接线程,检测线程中断,volatile-write,volatile-read等)。

是否可以确保{<1}}在获取之前无法移动 之后无法移动

并且保证{<1}}在获取之后(在发布之前或之后)都无法移动并且action 3无法移动 发布之前(获取之前或之后)?

对于编译器的重新排序操作,是否与边缘“双向障碍”同步?


编辑1 我担心这一点,因为如果同步 - 边缘不是双向重新排序障碍,编译器可以通过将锁获取移动到其他人来简单地创建死锁。

或者是双向重新排序障碍,甚至不需要阻止这种情况,因为锁定获取不能被推送到其他人,因为这会改变同步顺序?


编辑2 动作1,2,3和4是由JMM定义的“线程间动作”。


编辑3 这是一个示例,显示了重新排序如何导致死锁:

x和y是共享变量,syncA和syncB可以由任何其他线程获取。但是使用以下代码,可能没有死锁。

action 2

但是,如果将syncA的获取重新排序到syncB块中,则可能会导致死锁:

action 4

我认为这不是合法的编译器转换,因为它会改变同步顺序。我对这个假设是对的吗? Java内存模型(JMM)的哪个部分允许/禁止这个?

1 个答案:

答案 0 :(得分:2)

感谢assylias链接到this question,其中包含来自JSR-133 Cookbook的此图片的答案:

Reordering Rules Table

根据这张图片,EDIT 3的编译器转换是非法的,因为它重新排序了两个 MonitorEnters

此外,此表显示哪些同步边缘是&#34; 重新排序屏障&#34;其他操作。

感谢您的帮助:)