Can语句n!= n在多线程环境中返回true

时间:2012-09-24 05:38:51

标签: java multithreading

  

可能重复:
  How to simulate constructor race conditions?
  How to demonstrate race conditions around values that aren't published properly?

我从“java concurrency in practice”中获得了以下代码:

public class Holder{

  private int n;
  public Holder(int n){this.n = n;}
  public void assertSanity(){
     if(n != n) throw new AssertionError("This statement is false.");

  }


}

我只是想知道条件n != n,在某种情况下这是真的吗?

5 个答案:

答案 0 :(得分:2)

我的猜测是你在问这些问题:

我猜这本书正在谈论在完全构建对象之前共享对象的引用的可能性,所谓的行为是不正确的发布。

假设n != n分为以下几个步骤:

Access n on the right side of the operand
Access n on the left side of the operand
Compare values

然后,不难想象在前两个步骤之间n的值发生变化的情况。现在我知道你在想什么,“但n永远不会改变”。实际上,因为两个线程可以在该实例的构造函数完全运行之前共享对Holder实例的访问。

答案 1 :(得分:0)

据推测,编译器会将此优化为始终为false,但如果不是,那么是的,在多线程环境中它可以返回true。

假设左边的n被复制到一个寄存器。然后当前线程被中断,下一个线程修改n,然后我们返回第一个线程。现在右侧的n被复制到寄存器,然后调用比较操作(在两个寄存器上)。

在这种情况下,他们会有所不同。

编辑:如果你看下面nhantdh评论中的字节码,你会发现在n上执行了两次加载,因此在两者之间进行修改的中断可以使表达式评估为真。

答案 2 :(得分:0)

我认为理论上可能因为n不是volatile。这意味着一个线程可以构造一个Holder对象,但是为n设置的值对于在调用比较操作的不同核心上运行的另一个线程是不可见的。

答案 3 :(得分:0)

该值将始终相同。

只要变量是基本类型,变量是非静态的,并且您没有setter,您可以根据需要创建任意数量的类实例。 实例永远不会在变量'n'中共享相同的“对象”/实例。

如果再次在构造函数调用后更改值,则值可能不同,如setter或reflection。

答案 4 :(得分:-2)

我从C ++知道这个表达式。如果n不是数字,则可能是真的。见Checking if a double (or float) is NaN in C++