首先看一段比較經典的代碼: public static Singleton getInstance()
{
if (instance == null ) //0
{
synchronized (Singleton. class ) {
if (instance == null )
instance = new Singleton();
}
}
return instance;
}
在這段代碼裡,對instance == null 的兩次檢查就是我們所說的Double Check. 而對於為什麼要做兩次,網上的資料不勝枚舉,這裡就不多說了。
現在的問題是,這樣的double check 並不能保證安全執行緒。
關鍵在於Java 變數初始化以及賦值的順序。簡單地說,上面的程式中, instance = new Singleton() 這一句的操作過程是這樣的:
1。 為instance 分配空間
2。 將instance 指向港分配的空間
3。 為instance 賦值
可以看到,如果在完成步驟2 的時候,有一個新線程進入到上面程式中注0 的地方。那麼,將會發生的情況是不可預料的。
道理很簡單。可惜以訛傳訛的情況在網上太多了。
至於解決方案,只有定義執行個體變數的時候就完成初始化和賦值。比如: class Singleton
... {
private Vector v;
private boolean inUse;
private static Singleton instance = new Singleton();
private Singleton()
...{
v = new Vector();
inUse = true;
//...
}
public static Singleton getInstance()
...{
return instance;
}
}
或者,老老實實用synchronized 方法吧。
REF: http://www.ibm.com/developerworks/library/j-dcl.html