我有一个关于Java内存模型的问题。给出了以下示例:
action 1
action 2
synchronized(monitorObject) { //acquire
action 3
} //release
action 4acquire和release可以是任何同步-与边缘(锁定,解锁,启动线程,连接线程,检测线程中断,易失性写入,易失性读取等)
它是否保证在获得之前不能移动action 3,在发布后不能移动?
它是否保证action 2不能在获得之后被移动(无论是在发布之前还是之后),以及不能在发布之前(无论是在获得之前还是之后)移动action 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)的哪个部分允许/不允许这样做?
https://stackoverflow.com/questions/26724443
复制相似问题