【发布时间】:2012-10-27 14:56:58
【问题描述】:
JMM 中的因果关系似乎是其中最令人困惑的部分。我有几个关于 JMM 因果关系和并发程序中允许的行为的问题。
据我了解,当前的 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 和
then finally make r3 = 42 ,是不是违反了因果循环,因为现在已经没有因果区别了?
事实上,在同一份文档(第 15 页,图 7)中有一个示例,其中提到类似的因果循环是不可接受的。
那么为什么这个执行顺序在 JMM 中是合法的呢?
【问题讨论】:
标签: java concurrency compiler-optimization java-memory-model causality