多线程环境中的Java对象构造

den*_*iss 5 java concurrency multithreading object

我正在阅读这本名为"Java Concurrency in Practice"的书,作者给出了一个不安全的对象出版物的例子.这是一个例子.

public Holder holder;

public void initialize(){
   holder = new Holder(42);
}
Run Code Online (Sandbox Code Playgroud)

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.");
    }
}
Run Code Online (Sandbox Code Playgroud)

那么这是否意味着当其他线程甚至没有完全构造时,它可以访问一个对象?我想当线程A调用holder.initialize();和线程B调用时holder.assertSanity();,n != n如果线程A尚未执行,则不会满足条件this.n = n;

这是否也意味着如果我有一个更简单的代码,如

int n;

System.out.println(n == n); //false?
Run Code Online (Sandbox Code Playgroud)

Bre*_*ail 3

如果assertSanity方法在第一次和第二次加载之间被抢占,可能会出现问题n(第一次加载将看到0构造函数设置的值,第二次加载将看到构造函数设置的值),则可能会出现问题。问题是基本操作是:

  1. 为对象分配空间
  2. 调用构造函数
  3. holder为新实例

编译器/JVM/CPU 可以对步骤 #2 和 #3 重新排序,因为不存在内存屏障(最终的、易失性的、同步的等)。

从第二个示例中,不清楚“n”是局部变量还是成员变量,或者另一个线程如何同时改变它。