Jef*_* Li 11 java parallel-processing concurrency x86 jvm
在Java语言规范的第17章中,有一节解释了为什么"在一致性不充分之前发生".这是一个例子:
At first, x = y = 0
Thread 1 | Thread 2
r1 = x; | r2 = y;
if (r1 != 0) y = 1; | if (r2 != 0) x = 1;
Run Code Online (Sandbox Code Playgroud)
这是一个可能的执行跟踪:
r1 = x; // sees write of x = 1
y = 1;
r2 = y; // sees write of y = 1
x = 1;
Run Code Online (Sandbox Code Playgroud)
怎么会发生这种情况?令我困惑的是,当第一个动作看到x = 1时,是不是意味着条件r2!= 0变为真,因此y被分配给1?但按顺序,在r1 = x之后,y = 1.我在哪里弄错了理解这个例子?我该如何正确理解这个例子呢?
我相信这个例子在Java规范中提出的观点是Hans Boehm等人的观点.在Outlawing Ghosts中写一下,它指出了一些当代语言的记忆模型的缺陷(Java,C++ 11,甚至C++ 14仍然存在,但它们已经解决但没有解决这个问题).
关键在于:编写的程序通过语言规则正确同步.(如果你使用原子变量和memory_order_relaxed任何地方,在C++中也是如此.)但是,仍然不禁止发生意外行为.用Boehm来解释:机器可以推测出值为x1,然后执行得到的分支,然后(大概是当记忆最终响应时)验证推测是真的.确实找到了猜测,因为在此期间其他线程确实存储了x = 1,机器继续并且不会回滚推测的执行.
更糟糕的是,CPU确实可以推测存在任何价值.考虑这个修改的例子:
r1 = x | r2 = y
if (r1 != 0) y = r1 | if (r2 != 0) x = r2
Run Code Online (Sandbox Code Playgroud)
在这种情况下,x并y最终可能与任何价值,出于同样的原因.机器可以推测价值是任何东西,然后推测性地继续执行该假设,然后在众所周知的自我实现的预言中发现它的推测是真实的.
或许可以放心,目前没有真正的硬件表现如此.但重点是当代语言的记忆模型并不禁止这种行为.你引用的部分是Java试图说,"看,我们需要发生 - 之前的一致性,但这里的另一个奇怪的事情仍然不应该发生".在非规范性说明1.10/25中,C++ 14对此问题的看法同样模糊.
| 归档时间: |
|
| 查看次数: |
178 次 |
| 最近记录: |