我正在阅读一篇文章,其中实际上谈到了双重检查锁定,但我对作为示例的代码中更基本的失败感到惊讶。那里指出,实例的初始化(即在构造函数返回之前写入实例变量)可能会在对实例的引用写入共享变量(在下面的例子)。
Foo使用以下 class 定义,一个线程正在执行Foo.initFoo();,另一个线程正在执行System.out.println(Foo.foo.a);,第二个线程可能会打印0(而不是1或抛出 a NullPointerException),这是真的吗?
class Foo {
    public int a = 1;
    public static Foo foo;
    public static void initFoo() {
        foo = new Foo();
    }
    public static void thread1() {
        initFoo(); // Executed on one thread.
    }
    public static void thread2() {
        System.out.println(foo.a); // Executed on a different thread
    }
}
从我对 Java 内存模型(以及其他语言的内存模型)的了解来看,这实际上并不让我感到惊讶,但直觉强烈认为这是不可能的(可能是因为涉及对象初始化并且对象初始化似乎如此在 Java 中是神圣的)。
0是否可以在第一个线程中不同步的情况下“修复”此代码(即它永远不会打印)?