首先:是的,我知道在 Java 中做单例的最好方法是使用enum
s,但是如果由于某种原因你需要子类化一个单例类,你不能使用枚举,所以......
JavaWorld 的 David Geary 很久以前发表了一篇关于在 Java 中实现单例的文章。他认为以下对线程安全单例实现的优化是有问题的:
public static Singleton getInstance()
{
if (singleton == null)
{
synchronized(Singleton.class)
{
if(singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
(查看更多信息:http ://www.javaworld.com/javaworld/jw-04-2003/jw-0425-designpatterns.html?page=4#sthash.G8lzWOfT.dpuf )
Geary 说这种“双重检查锁定”优化
不能保证工作,因为编译器可以在调用单例的构造函数之前自由地为单例成员变量赋值。如果发生这种情况,线程 1 可以在单例引用被分配之后但在单例初始化之前被抢占,因此线程 2 可以返回对未初始化单例实例的引用。
我的问题:以下更改是否可以解决该问题?我已经开始阅读 Goetz 的 Java 并发书,似乎允许编译器对线程内操作进行混洗,所以我不太有信心......不过,在我看来,这singleton = temp;
是一个原子操作,在这种情况下,我认为它应该。请解释。
public static Singleton getInstance()
{
if (singleton == null)
{
synchronized(Singleton.class)
{
if(singleton == null) {
Singleton temp = new Singleton();
singleton = temp;
}
}
}
return singleton;
}