Thread Safe Efficient way to implement singleton pattern in Java?
Possible Duplicate:
Efficient way to implement singleton pattern in Java
我在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(); }
}
但是find bugs实用程序在这方面给出了两个错误:1。双重空检查。2。静态字段的延迟初始化不正确。
最好的方法是什么?
这是正确的吗?
1
2
3
4
5 synchronized (Singleton.class) {
if (singleton== null) {
singleton= new Singleton();
}
}
最有效/最简单的方法就是
1 2 3 | enum Singleton { INSTANCE } |
注意:不需要锁定,因为类加载是线程安全的。类在默认情况下是最终的,不能通过反射调用构造函数。在使用实例或类之前,不会创建实例。如果你担心这个类可能会被意外使用,你可以将这个单例包装在一个内部类中。
1 2 3 4 5 6 7 8 9 | final class Singleton { private Singleton() { } static class SingletonHolder { static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.INSTANCE; } } |
嗯,你必须非常偏执,才能认为这是一个更好的解决方案。
关于这个问题已经写了很多。是的,简单的双重检查锁定模式不安全。但您可以通过将静态实例声明为volatile来确保安全。新的Java内存模型规范在处理易失性时增加了编译器的一些代码重排序限制,因此原始风险消失了。
无论如何,在创建实例时,我很少真正需要这种懒散,所以我通常只是在类加载时静态地创建它:
1 | private static MyClass instance = new MyClass(); |
这是简明扼要的。另一种选择是,如果您真的想让它变得懒惰,您可以利用类加载特性,并执行以下操作:
1 2 3 4 5 6 7 8 9 10 | public class MyClass { private static class MyClassInit { public static final MyClass instance = new MyClass(); } public static MyClass getInstance() { return MyClassInit.instance; } ... } |
在第一次调用GetInstance()之前,不会加载嵌套类。
在Java中实现单模式的有效方法的第一个代码示例是线程安全。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public final class Foo { private static final Foo INSTANCE = new Foo(); private Foo() { if (INSTANCE != null) { throw new IllegalStateException("Already instantiated"); } } public static Foo getInstance() { return INSTANCE; } } |
(从Java中实现单模式的有效方法中复制了什么?)
问题中的第二个代码示例是正确的,并且是线程安全的,但是它会在每次调用