【发布时间】:2010-08-30 14:58:29
【问题描述】:
仅限 Java 5 及更高版本。假设一台多处理器共享内存计算机(您现在可能正在使用一台)。
下面是单例延迟初始化的代码:
public final class MySingleton {
private static MySingleton instance = null;
private MySingleton() { }
public static MySingleton getInstance() {
if (instance == null) {
synchronized (MySingleton.class) {
if (instance == null) {
instance = new MySingleton();
}
}
}
return instance;
}
}
是否必须将 instance 声明为 volatile 以防止优化器重写 getInstance() 如下(这在顺序程序中是正确的):
public static MySingleton getInstance() {
if (instance == null) {
synchronized (MySingleton.class) {
// instance must be null or we wouldn't be here (WRONG!)
instance = new MySingleton();
}
}
}
假设优化器不重写代码,如果instance没有声明volatile是否仍然保证在退出synchronized块时被刷新到内存,并在synchronized块时从内存中读取输入了吗?
编辑:我忘记将 getInstance() 设为静态。我认为这不会改变答案的有效性;你们都知道我的意思。
【问题讨论】:
-
提示:您可以使用
javap -c com.example.ClassName反汇编代码,以便检查它是如何编译的,以及编译器是否更改/优化了其中一个。我用 JDK 1.6 之一为你检查了它,编译器没有去掉嵌套的if。 -
使用 javap 很有趣,但 javac 中的优化器通常很差。故意。真正的优化器在运行时的 JIT 编译器中。
-
我很抱歉只将其中一个答案选为“答案”。到目前为止,所有这些都值得检查,但它只能让我检查一个。
-
volatile 不是必要的。公众对双重检查锁定的了解已经过时了。
-
信誉不佳,能解释一下吗?
标签: java volatile synchronized double-checked-locking