微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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.

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

感谢您的帮助 :)

原文地址:https://www.jb51.cc/java/125830.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐