我正在阅读一篇文章,其中实际上谈到了双重检查锁定,但我对作为示例的代码中更基本的失败感到惊讶。那里指出,实例的初始化(即在构造函数返回之前写入实例变量)可能会在对实例的引用写入共享变量(在下面的例子)。
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
是否可以在第一个线程中不同步的情况下“修复”此代码(即它永远不会打印)?