在Java中如何理解“发生之前的一致性是不够的”

chapter 17 of Java language specification年,有一个部分解释为什么“前后一致性不足”.这里是例子:
At first,x = y = 0
Thread 1            | Thread 2
r1 = x;             | r2 = y; 
if (r1 != 0) y = 1; | if (r2 != 0) x = 1;

这里有一个可能的执行痕迹:

r1 = x;  // sees write of x = 1
y = 1;
r2 = y;  // sees write of y = 1
x = 1;

怎么会这样呢?我感到困惑的是,当第一个动作看到x = 1时,这并不意味着条件r2!= 0成为真,因此y已被分配给1.但是按照这个顺序,y = 1在r1 = x之后.我在哪里弄错了例子?我该如何正确解释这个例子?

解决方法

我相信这个例子在Java规范中的观点是Hans Boehm等人写在 Outlawing Ghosts年,它指出了一些当代语言的记忆模型(Java,C 11,甚至C 14,仍然解决,但没有解决这个问题)的缺陷.

要点是这样:程序按照书面的规则被语言的规则正确同步. (在C中,如果你使用原子变量和memory_order_relaxed到处都是如此)但是,仍然不会发生意外行为.说明Boehm:机器可以推测x的值,例如x为1,然后执行结果分支​​,稍后(大概是当内存终于响应时)验证猜测是否为真.确实发现猜测,因为在另一个线程确实存储x = 1,机器继续并且不回滚推测的执行.

更糟糕的是,cpu真的可以推测任何价值存在.考虑这个修改的例子:

r1 = x                     |  r2 = y
if (r1 != 0) y = r1        |  if (r2 != 0) x = r2

在这种情况下,由于相同的原因,x和y可能会以任何值结束.机器可以推测价值是什么,然后推测继续执行这个假设,后来发现它的猜测是真实的,在谚语的自我实现的预言.

这可能令人放心,目前没有真正的硬件表现如此.但关键是当代语言的记忆模式并不能阻止这种行为.您引用的部分是Java尝试说:“看,我们需要在一致性之前发生,但这个另外奇怪的事情在这里仍然不应该发生”.在非规范性说明1.10 / 25中,C 14对这个问题也有同样的含糊的意见.

相关文章

最近看了一下学习资料,感觉进制转换其实还是挺有意思的,尤...
/*HashSet 基本操作 * --set:元素是无序的,存入和取出顺序不...
/*list 基本操作 * * List a=new List(); * 增 * a.add(inde...
/* * 内部类 * */ 1 class OutClass{ 2 //定义外部类的成员变...
集合的操作Iterator、Collection、Set和HashSet关系Iterator...
接口中常量的修饰关键字:public,static,final(常量)函数...