不一致的状态比较 Java

Inconsistent State Comparison Java

Java并发实践中给出了一个例子*来演示可见性问题,由于缺乏同步,两个不同的线程可能看不到任何特定可变对象的最新状态。

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.");
        }
    }

在这个特定的示例中,书中指出 Thread "A" 应该首先通过 Thread 不安全的方式初始化并发布它,例如:

public Holder holder;
public void initialize() {
    holder = new Holder(42);
}

然后线程 "B" 调用 holder.assertSanity(),由于状态不一致,完全有可能抛出 AssertionError

现在,我理解了该论点的基本前提,即对可变变量所做的更改可能永远不会被另一个线程观察到。但我在这里感到困惑的是,它正在比较相同的(或者我认为)参考 n != n

这不是比较可变原始字段的值private int n吗?不管 n 现在对线程 A 的值可能是 42,对线程 B 的值是 0(默认值),不应该直接调用来检查它在 same[ 中的值=39=]线程是一致的?即,在线程 A 中调用 assertSanity() 将检查是否 42 != 42,而在线程 B 中调用 0 != 0?

*引用自 3.5 Safe Publication,书中的清单 3.14 和 3.15。

问题是在表达式 n != n 中变量 n 将被加载两次(假设没有优化字节码)。在这两个负载之间,另一个线程可以更改该值。

在线程 B n != n 比较期间,B 检索 n 两次。同时,在线程 A 中运行的构造函数会将 n 的值从默认值 0 修改为 42。