加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

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

发布时间:2020-12-14 16:19:53 所属栏目:Java 来源:网络整理
导读:我有一个关于 Java内存模型的问题.给出以下示例: action 1action 2synchronized(monitorObject) { //acquire action 3} //releaseaction 4 获取和释放可以是任何与边缘同步的(锁定,解锁,启动线程,连接线程,检测线程中断,易失性写入,易失性读取等) 是否保证
我有一个关于 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.

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

感谢您的帮助 :)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读