线程安全在Java中实现单例模式的有效方法?
Possible Duplicate:
Efficient way to implement singleton pattern in Java
我正在读这个Best Singleton Implementation In Java,但它不是线程安全的
根据维基:
if(singleton==null) { synchronized(Singleton.class) { // this is needed if two threads are waiting at the monitor at the // time when singleton was getting instantiated if(singleton==null) singleton= new Singleton(); }
}
但是查找bug实用程序在这方面给出了两个错误: 1.双重空检查。 2.静态字段的延迟初始化不正确
最好的办法是什么,
是否正确:
synchronized (Singleton.class) { if (singleton== null) { singleton= new Singleton(); } }
# 1 楼答案
创建延迟加载单例的最有效/最简单的方法是
注意:不需要锁定,因为类加载是线程安全的。默认情况下,该类是final,不能通过反射调用构造函数。在使用实例或类之前,不会创建实例。如果您担心该类可能被意外使用,可以将该单例封装在内部类中
IMPO,你必须非常偏执,认为这是一个更好的解决方案。# 2 楼答案
对于Efficient way to implement singleton pattern in Java的接受答案中的第一个代码示例是线程安全的。创建
INSTANCE
由类加载器在第一次加载类时执行;它以线程安全的方式执行一次:(抄自What is an efficient way to implement a singleton pattern in Java?)
问题中的第二个代码示例是正确的并且是线程安全的,但是它会导致对
getInstance()
的每次调用都进行同步,这会影响性能# 3 楼答案
关于这个问题已经写了很多文章。是的,简单的双重检查锁定模式不安全。但是,您可以通过将静态实例声明为volatile来确保安全。新的Java内存模型规范在处理volatile时为编译器添加了一些代码重新排序限制,因此原有的风险消失了
无论如何,我在创建实例时很少真正需要这种懒散,所以我通常只是在类加载时静态创建它:
这是简短明了的。作为替代方案,如果您真的想让它变懒,您可以利用类加载特性并执行以下操作:
在您第一次调用getInstance()之前,不会加载嵌套类