在JSR-133中,有两个例子表明状态可能是正确同步的程序。
第一个例子由图6给出:
x == y == 0
然后,线程1通过以下方式修改状态:
r1 = x;
if (r1 != 0)
y = 1;
和线程2通过以下方式修改状态:
r2 = y;
if (r2 != 0)
x = 1;
作者声明此程序已正确同步,但是,此程序的执行导致r1 == r2 == 1
。后一个价值怎么可能呢?
此外,图7表示初始状态:
x == y == 0
修改主题1:
r1 = x;
y = r1;
和线程2执行:
r2 = y;
x = r2;
这怎么会导致r1 == r2 == 42
?
答案 0 :(得分:1)
图6 是JMM的 out of an air air 限制的示例。由于没有字段标记为volatile
,因此通常允许JVM对示例代码应用优化。这可能会导致惊人的结果。
假设线程1 观察到x = 1
为真。现在不要担心,情况可能如此。在这种情况下,线程将设置y = 1
。然后,后一种观察将证明x = 1
初始观察到的是循环推理的合理性。如果这是真的,x = y = 1
将是一个合法的结果,JVM可以简单地替换两个线程中的代码来写每个值。 JMM禁止这种推理形式,x = y = 0
是根据JMM的唯一合法结果。
在图7 中提出了类似的论点。再次,假设线程1 观察x = 42
。在这种情况下,线程会写y = 42
。根据这一观察,人们现在可以争辩说,之前的x = 42
是一种法律观察。然而,最初的假设是凭空捏造被禁止的事情,x = y = 0
是唯一合法的结果。
发生之前关系的定义仅适用于明确同步的程序,并且不会禁止假设的循环推理。因此,需要凭空限制。这当然是学术性的,但JMM是一个学术模型,仍然需要定义这个限制。
因此,在任何一个图中都没有值x
或y
可以采用的比赛条件,即没有比赛条件,x = y = 0
是唯一可能的观察。因此,尽管没有volatile
。
答案 1 :(得分:0)
之前发生的模型仅基于与同步并且在边缘之前发生。 JLS提供了发生在之前一致执行的示例:
r1 = x; // sees write of x = 1
y = 1;
r2 = y; // sees write of y = 1
x = 1;
在这个例子中,这些值出现在空中"它是发生 - 在之前一致但是打破了因果关系要求(没有顺序一致的执行可以产生这个结果)。因此,这样的执行不是合法的执行。
r1 === r2 == 42
是有效的结果。
没有同步,但唯一有效的结果是所有值都为0,因为没有为变量分配其他值。例如,在y = r1
中,r1
的默认值(0)或值x
(0) - 在这两种情况下y
都为0。 / p>
作为旁注,您应该阅读Chapter 17 of the JLS而不是原始的JSR。