Can语句n!= n在multithreading环境中返回true

可能重复:
如何模拟构造函数的竞争条件?
如何certificate未正确发布的值的竞争条件?

我从“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 ,在某种情况下这可能是真的吗?

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

  • 如何certificate未正确发布的值的竞争条件?
  • 如何模拟构造函数的竞争条件?

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

假设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实例的访问。

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

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

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

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

编辑:如果你看下面nhantdh的注释中的字节码,你会看到在n上执行了两个加载,因此在两者之间进行修改的中断可以使表达式计算为true。

值始终相同。

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

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

我从C ++知道这个表达式。 如果n不是数字,则可能是真的。 请参阅在C ++中检查double(或float)是否为NaN