java – 同步 – 与edegs编译器在两个方向重新排序障碍?

我有一个关于 Java内存模型的问题.给出以下示例:
action 1
action 2
synchronized(monitorObject) { //acquire
    action 3
} //release
action 4

获取和释放可以是任何与边缘同步的(锁定,解锁,启动线程,连接线程,检测线程中断,易失性写入,易失性读取等)

是否保证在收购之前无法移动动作3,在发布后不能移动?

并且保证行为2在获得后不能移动(既不在释放之前也不在释放之后),并且动作4在释放之前不能移动(在获取之前和之后)?

同步 – 与边缘“双向屏障”编译器的重新排序动作?

编辑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 */  }

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

y = 0;
synchronized(syncB) {
    y = 1;
    synchronized(syncA) {
        x = 1;
    }
}

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

解决方法

感谢 assylias链接this question,其中包含从 JSR-133 Cookbook的这个图像的答案:

根据这个图像,编辑器从EDIT 3转换是非法的,因为它重新排列两个MonitorEnters.

此外,该表还显示了哪些同步边缘是什么样的“重新排序障碍”,为其他操作.

感谢您的帮助 :)

相关文章

最近看了一下学习资料,感觉进制转换其实还是挺有意思的,尤...
/*HashSet 基本操作 * --set:元素是无序的,存入和取出顺序不...
/*list 基本操作 * * List a=new List(); * 增 * a.add(inde...
/* * 内部类 * */ 1 class OutClass{ 2 //定义外部类的成员变...
集合的操作Iterator、Collection、Set和HashSet关系Iterator...
接口中常量的修饰关键字:public,static,final(常量)函数...