[英]Is this code correct example of thread safe Singleton design pattern?
[英]Is this singleton pattern thread safe?
我有一个单例服务器实例,我很好奇我的代码是否是线程安全的。 我已经阅读了不同的单例模式,我认为通常的方法是double-checked locking
模式,如下所示:
public static Singleton getInstance() {
if(singleton == null) {
synchronized(Singleton.class) {
if(singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
这被认为是设置/获取单身的有效线程安全方式。 我读过,获取和设置单例的最简单方法是lazy instantiation
,如下所示:
public static ClassicSingleton getInstance() {
if(instance == null) {
instance = new ClassicSingleton();
}
return instance;
}
现在我想知道的是我的变体是否是线程安全的。 我的代码:
public static void startServer(int listeningPortNumber) throws IOException {
if (server != null) {
throw new IOException("Connection exists");
}
server = new Server(listeningPortNumber);
}
我的代码与上面的惰性实例化模式非常相似,但我看不出我的代码是如何不是线程安全的。 有没有我没看到的东西,或者这是真正有效的代码?
参考: http : //www.javaworld.com/article/2073352/core-java/simply-singleton.html
这不安全。
想象一下如果两个线程同时调用startServer
(或者足够接近它)会发生什么:
server != null
,并看到该server
为空 - 因此它不会抛出异常 new Server(listeningPortNumber);
如果server
不是volatile
,问题就更糟了,因为你甚至不再需要交错 - 线程A可能实例化new Server(...)
,但写入server
字段是'线程B看了很长时间(可能永远),因为它没有刷新到主存储器。
但是,即使server
是volatile
,由于交错,该方法也很有效。
不,懒惰的单例模式不是线程安全的。
如果你想在Java中使用线程安全版本的Singleton模式,你应该实现Bill Pugh的解决方案。 代码在这里:
public class OptimalSingleton
{
protected OptimalSingleton()
{
// ...
}
private static class SingletonHolder
{
private final static OptimalSingleton INSTANCE = new OptimalSingleton();
}
public static OptimalSingleton getInstance()
{
return SingletonHolder.INSTANCE;
}
}
关于SO的更多信息: Singleton模式(Bill Pugh的解决方案)
您的代码不是线程安全的。
假设您有两个线程,A和B,它们调用startServer(...)
,而在这些调用之前,服务器尚未初始化。 A传递一个值(a),B传递另一个值(b)到该方法。 您唯一知道的是,在每个线程中定义了操作的顺序。
所以以下是可能的:
A: check server != null (false)
B: check server != null (false)
A: server = new Server(a)
B: server = new Server(b)
显然,这违反了单身人士。 线程A将看到一个初始化为与传入的值不同的值的服务器,并且从未抛出异常。
您的代码不是线程安全的! 假设2个不同的线程同时调用startServer方法两者都看到服务器变量为null所以将跳过if块并且每个线程创建一个Server实例! 因此,您将在应用程序中以2个服务器实例结束。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.