我正在阅读一篇文章,其中涉及双重检查锁定,但我对作为示例提供的代码中更基本的失败感到惊讶.在那里声明,实例的初始化(即,在构造函数返回之前发生的实例变量的写入)可能会在对实例的引用写入共享变量(在静态字段中)之后重新排序.以下示例).
是否正确使用以下类定义Foo,一个线程执行Foo.initFoo();并执行不同的线程System.out.println(Foo.foo.a);,第二个线程可以打印0(而不是1或抛出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
}
}
Run Code Online (Sandbox Code Playgroud)
根据我对Java内存模型(以及其他语言中的内存模型)的了解,实际上我并不感到惊讶,这是可能的,但直觉投票非常强烈,因为它是不可能的(可能因为涉及对象初始化而对象初始化似乎如此在Java中神圣).
如果0没有第一个线程中的同步,是否可以"修复"此代码(即它永远不会打印)?