是否可以对实例初始化和分配给共享变量进行重新排序?
我正在阅读一篇文章,它实际上谈到了双重检查锁定,但我对作为示例提供的代码中更基本的失败感到惊讶。其中指出,实例的初始化(即写入构造函数返回之前发生的实例变量)可能会在将实例的引用写入共享变量(以下示例中的静态字段)之后重新排序。
在类的以下定义中,当一个线程执行而另一个线程执行时,第二个线程可以打印(而不是或抛出一个)这是真的吗?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
}
}
根据我对Java内存模型(以及其他语言中的内存模型)的了解,这实际上并不让我感到惊讶,这是可能的,但直觉非常强烈地投票支持它是不可能的(也许是因为涉及对象初始化,对象初始化在Java中似乎如此神圣)。
是否有可能“修复”此代码(即它永远不会打印)而不在第一个线程中进行同步?0