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)的哪个部分允许/不允许这样做?
感谢assylias链接到这个问题,其中包含JSR-133 Cookbook中这张图片的答案:

根据此图像,来自 EDIT 3 的编译器转换是非法的,因为它重新排序了两个MonitorEnters。
此外,该表还显示哪些同步边缘是哪些类型的“重新排序屏障”,用于哪些其他操作。
感谢您的帮助 :)
| 归档时间: |
|
| 查看次数: |
183 次 |
| 最近记录: |