toc*_*777 70 java singleton design-patterns locking double-checked-locking
从Head First设计模式书中,具有双重检查锁定的单例模式已实现如下:
public class Singleton {
private volatile static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
Run Code Online (Sandbox Code Playgroud)
我不明白为什么volatile被使用.volatile使用不会 破坏使用双重检查锁定的目的,即性能?
Tim*_*der 63
理解为什么一个很好的资源volatile需要来自JCIP书.维基百科对该材料也有不错的解释.
真正的问题是Thread A可以instance在完成构建之前为其分配内存空间instance.Thread B将看到该任务并尝试使用它.这导致Thread B失败,因为它使用的是部分构造的版本instance.
Rav*_*abu 18
正如@irreputable引用的那样,不稳定并不昂贵.即使价格昂贵,也应优先考虑性能.
Lazy Singletons还有一个更干净优雅的方式.
public final class Singleton {
private Singleton() {}
public static Singleton getInstance() {
return LazyHolder.INSTANCE;
}
private static class LazyHolder {
private static final Singleton INSTANCE = new Singleton();
}
}
Run Code Online (Sandbox Code Playgroud)
源文章:来自维基百科的initialization-on-demand_holder_idiom
在软件工程中,Initialization on Demand Holder(设计模式)习语是一个懒惰的单例.在所有版本的Java中,这个习惯用法都能实现安全,高度并发的延迟初始化,并具有良好的性能
由于该类没有任何static初始化变量,因此初始化很简单.
LazyHolder在JVM确定必须执行LazyHolder之前,不会初始化其中的静态类定义.
静态类LazyHolder仅getInstance在类Singleton上调用静态方法时执行,并且第一次发生这种情况时,JVM将加载并初始化LazyHolder类.
此解决方案是线程安全的,无需特殊的语言结构(即volatile或synchronized).
alf*_*alf 10
好吧,没有双重检查锁定的性能.这是一个破碎的模式.
抛开情绪,这volatile是因为没有它,当第二个线程通过时instance == null,第一个线程可能还没有构建new Singleton():没有人承诺对象的创建发生 - 在instance为任何线程分配之前,但实际创建对象的线程.
volatile反过来确定读取和写入之间发生的关系,并修复损坏的模式.
如果您正在寻找性能,请使用holder inner static class.