JMM中的因果关系似乎是最令人困惑的部分。我有几个关于JMM因果关系的问题,并允许并发程序中的行为。为什么在Java内存模型中允许这种行为?
据我所知,目前的JMM总是禁止因果关系循环。 (对吗?)现在
,按照该JSR-133文档,24页,图16中,我们有一个例子:
最初x = y = 0
主题1:
r3 = x;
if (r3 == 0)
x = 42;
r1 = x;
y = r1;
线程2:
r2 = y;
x = r2;
直观上,r1 = r2 = r3 = 42
似乎不可能。但是,它不仅被提及,而且在JMM中也是“允许的”。
对于可能性,从中我无法理解该文档的解释是:
编译器可确定曾经分配给
x
值只有 0和42从这一点,编译器可能推测,在我们执行r1 = x
的点 处,我们刚刚执行了42到x
的写入,或者我们刚刚读取了x
并看到了值42.在任何一种情况下,它都会合法读取x
查看价值 42.然后它可以将r1 = x
更改为r1 = 42
;这将允许y = r1
转换为y = 42
并且执行得更早,导致 有问题的行为。在这种情况下,首先写入y
承诺 。
我的问题是,究竟是什么样的编译器优化? (我是编译器无知的。)由于42仅仅是有条件地写入的,所以当满足if
语句时,编译器如何决定去编写x
?
其次,即使编译器这个投机的优化,并承诺y = 42
和 然后最后使得r3 = 42
,是不是违反了因果循环的,因为没有原因,现在的效果区别剩下什么?
实际上,在同一文件(第15页,图7)中有一个例子,其中提到了一个类似的因果回路,因为这是不可接受的。
那么这个执行命令在JMM中怎么合法呢?
@Alexei这解释了一些。但是,编译器不应该使用'r3 = 0'而不是'r3 = 42'吗?或者他们只是在展示'一种可能性'! – gaganbm
编译器不会生成'r3 = 42',它只会使'r3 = x'完好无损。编译器优化并不总是以最大深度执行。如果优化可能违反正确性的可能性很小,则会被放弃。在给定的代码中,不存在这样的情况,但是如果存在其他代码,则它们可以出现。另外,编译器可以决定'r3 = 0'与'r3 = x'的价格相同。 –