Singleton design pattern broken?
Possible Duplicate:
Efficient way to implement singleton pattern in Java
我本以为下面的类是线程安全的单线程类,但阅读http://taskinoor.wordpress.com/2011/04/18/singleton_multiphreaded/似乎不是。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public class ThreadSafeSingleton { private static ThreadSafeSingleton ref; private ThreadSafeSingleton(){ } public ThreadSafeSingleton getSingletonObject(){ if(ref == null){ ref = new ThreadSafeSingleton(); } return ref; } } |
根据文章,唯一真正的线程安全单例是-
1 2 3 4 5 6 7 8 9 10 11 12 13 | public class ThreadSafeSingleton { private static ThreadSafeSingleton ref = new ThreadSafeSingleton(); private ThreadSafeSingleton(){ } public ThreadSafeSingleton getSingletonObject(){ return ref; } } |
这是正确的吗?
这不是唯一的线程安全单例,但这是正确的。另一种方法是同步在第一个示例中创建单例实例的代码。但问题在于,您必须同步代码,这可能是问题,也可能不是问题。另一个可能的问题是singleton没有被延迟初始化。同样,根据体系结构和需求,它可能是问题,也可能不是问题。还有另一个奇怪的模式来处理这个问题:http://en.wikipedia.org/wiki/initialization_on_demand_holder_习语。
是的,文章是正确的。
在上面的示例中,如果同时由两个函数调用该方法,则它们可能都将
在下面的示例中,当类被加载时,
是的,是正确的。
在第一种情况下,如果两个线程同时调用
在第二种情况下,该方法只返回对在类加载期间创建的现有对象的引用,这是由JVM以线程安全的方式完成的。
在线程安全性方面,第二个比第一个要好得多。
实现ThreadSafe单例对象有几种不同的方法。静态初始化(底部方法)就是其中之一。
还可以使用静态内部类、依赖项注入、同步EDCOX1×5、甚至是Java 5 +中的双重检查锁定模式,只要HER变量被声明为EDCOX1×6。有关更多信息,请参见实践中的Java并发。
其中,如果必须构建实际的单例,我更喜欢第一种方法。否则,我喜欢以图形的形式使用范围。
1 2 3 4 5 6 | if(ref == null) { ref = new ThreadSafeSingleton(); } return ref; |
两个线程在大致相同的时间运行可能会撞击
在这段代码中没有任何机制可以阻止上面描述的竞争条件。