7

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

我从《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,在某种情况下可能是这样吗?</p>

4

5 回答 5

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的构造函数完全运行之前,两个线程可以共享对该实例的访问。

于 2012-09-24T05:51:14.063 回答
0

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

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

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

编辑:如果您查看下面 nhantdh 注释中的字节码,您会看到在 n 上执行了两次加载,因此两者之间的修改中断可能导致表达式评估为真。

于 2012-09-24T05:43:32.027 回答
0

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

于 2012-09-24T05:57:07.630 回答
0

该值将始终相同。

只要变量是原始类型,变量是非静态的并且您没有设置器,您就可以创建任意数量的类实例。这些实例永远不会在变量“n”中共享相同的“对象”/实例。

如果您在再次调用构造函数后更改该值,则该值可能会有所不同,例如 setter 或反射。

于 2012-09-24T06:57:15.363 回答
-2

我从 C++ 中知道这个表达式。n如果不是数字,它可以是真的。请参阅在 C++ 中检查双精度(或浮点数)是否为 NaN

于 2012-09-24T05:43:34.823 回答