![](/img/trans.png)
[英]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.