懶漢式單例:在第一次被引用時才會將自己執行個體化。
class Singleton
{
private static Singleton instance;
//程式運行時建立一個靜態唯讀進程輔助對象
private static readonly object syncRoot = new object();
//構造方法讓其private,外界就無法使用new建立執行個體
private Singleton()
{
}
//獲得本類執行個體的唯一全域訪問點
public static Singleton GetInstance()
{
/*
* 先判斷執行個體是否存在,不存在再加鎖處理。這樣不用讓線程每次都加鎖,而只是在執行個體未被建立的時候再加鎖處理。同時也能保證多安全執行緒。
* 這種做法被稱Double-Check Locking(雙重鎖定)。
* 兩次判斷instance==null是因為當同時有兩個線程調用GetInstance()方法時,它們將可以通過第一重instance==null的判斷,然後由於lock機制,
* 這兩個線程則只有一個進入,另一個在外排隊等候,必須要其中的一個進入並出來後,另一個才能進入。而此時如果沒有了第二重的instance是否為
* null的判斷,則第一個線程建立了執行個體,而第二個線程還是可以繼續再建立新的執行個體,這就沒有達到單例的目的。
*/
if (instance == null)
{
//在同一個時刻,只有一個線程可以進入
lock (syncRoot)
{
//若執行個體不存在,則new一個新的執行個體,否則返回已有的執行個體
if (instance == null)
{
instance = new Singleton();
}
}
}
return instance;
}
}
餓漢式代例:自己被載入時就將自己執行個體化。
/// <summary>
/// 靜態初始化方法
/// C#與公用語言運行庫也提供了一種‘靜態初始化’方法,這種方法不需要開發人員顯式地編寫安全執行緒代碼,即可解決多線程環境下它是不安全的問題。
/// </summary>
sealed class Singletom2
{
//sealed 陰止發派生,而派生可能會增加執行個體
//在第一次引用類的任何成員時建立執行個體。公用語言運行庫負責處理變數初始化
private static readonly Singletom2 instance = new Singletom2();
private Singletom2() { }
public static Singletom2 GetInstance()
{
return instance;
}
}
靜態初始化方式提前佔用系統資源,懶漢方式面臨多線程訪問安全性問題。從C#語言角度來講,餓漢式的單例類已經足夠滿足我們的需求了。