【发布时间】:2013-04-15 08:50:10
【问题描述】:
我正在阅读an essay,它实际上谈到了双重检查锁定,但我对作为示例的代码中更基本的故障感到惊讶。那里指出,实例的初始化(即在构造函数返回之前写入实例变量)可能会被重新排序到在实例的引用被写入共享变量(以下示例中的静态字段)。
对于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)?
【问题讨论】:
-
您的代码似乎缺少 System.out.println() 就像您描述的那样。能贴出完整的代码吗?
-
它也缺少对
Foo.initFoo()的调用。我已将语句添加为单独的静态函数,该函数将在不同线程上调用,而不会在线程之间进行同步。
标签: java concurrency