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

Min*_*ock 10 java multithreading memory-model compiler-optimization java-memory-model

我有一个关于Java内存模型的问题.给出以下示例:

action 1
action 2
synchronized(monitorObject) { //acquire
    action 3
} //release
action 4
Run Code Online (Sandbox Code Playgroud)

acquire并且release可以是任何与边缘同步(锁定,解锁,启动线程,连接线程,检测线程中断,易失性写入,易失性读取等)

它是保证action 3不能被移动之前的获取和不能被移动的释放?

而且是保证action 2不能被移动的获取(无论是发布之前,也没有之后),并且action 4不能移动之前的版本(无论是acquire之前也不之后)?

那么与编译器的重新排序操作同步 - 边缘" 双向障碍 "?


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

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


编辑2 操作1,2,3和4是JMM定义的" 线程间操作 " .


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

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

/* 1 */  synchronized(syncA) {
/* 2 */      x = 1;
/* 3 */  }
/* 4 */  y = 0;
/* 5 */  synchronized(syncB) {
/* 6 */      y = 1;
/* 7 */  }
Run Code Online (Sandbox Code Playgroud)

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

y = 0;
synchronized(syncB) {
    y = 1;
    synchronized(syncA) {
        x = 1;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Min*_*ock 2

感谢assylias链接到这个问题,其中包含JSR-133 Cookbook中这张图片的答案:

重新排序规则表

根据此图像,来自 EDIT 3 的编译器转换是非法的,因为它重新排序了两个MonitorEnters

此外,该表还显示哪些同步边缘是哪些类型的“重新排序屏障”,用于哪些其他操作。

感谢您的帮助 :)