單例模式又分爲懶漢模式與餓漢模式。安全
懶漢式單例類在第一次使用時建立,無須一直佔用系統資源,實現了延遲加載,可是必須處理好多個線程同時訪問的問題,特別是當單例類做爲資源控制器,在實例化時必然涉及資源初始化,而資源初始化頗有可能耗費大量時間,這意味着出現多線程同時首次引用此類的機率變得較大,須要經過雙重檢查鎖定等機制進行控制,這將致使系統性能受到必定影響。多線程
/// <summary> /// 懶漢模式(雙重鎖定) /// </summary> public class SingletonLazy { //定義一個靜態變量來保存類的實例 private static SingletonLazy instance; //定義一個標識確保線程同步 private static readonly object locker = new object(); //定義私有構造函數,使外界不能建立該類實例 private SingletonLazy() { } /// <summary> /// 定義公有方法提供一個全局訪問點,同時你也能夠定義公有屬性來提供全局訪問點 /// </summary> /// <returns></returns> public static SingletonLazy GetInstance() { //當第一個線程運行到這裏時,此時會對locker對象 "加鎖", //當第二個線程運行該方法時,首先檢測到locker對象爲"加鎖"狀態,該線程就會掛起等待第一個線程解鎖 //lock語句運行完以後(即線程運行完以後)會對該對象"解鎖" //第一重判斷,先判斷實例是否存在,不存在再加鎖處理 if (instance == null) { //加鎖的程序在某一時刻只容許一個線程訪問 lock (locker) { //第二重判斷,若是類的實例不存在則建立,不然直接返回 if (instance == null) { instance = new SingletonLazy();//建立單例實例 } } } return instance; } }
餓漢式單例類在類被加載時就將本身實例化,它的優勢在於無須考慮多個線程同時訪問的問題,能夠確保實例的惟一性;從調用速度和反應時間角度來說,因爲單例對象一開始就得以建立,所以要優於懶漢式單例。可是不管系統在運行時是否須要使用該單例對象,因爲在類加載時該對象就須要建立,所以從資源利用效率角度來說,餓漢式單例不及懶漢式單例,並且在系統加載時因爲須要建立餓漢式單例對象,加載時間可能會比較長。函數
/// <summary> /// 餓漢模式(線程安全且不用用鎖) /// </summary> public sealed class Singleton { //readonly和static一塊兒使用,用於指定該常量是類別級的,它的初始化交由靜態構造函數實現,並能夠在運行時編譯。 //在這種模式下,無需本身解決線程安全性問題,CLR會給咱們解決。 //由此能夠看到這個類被加載時,會自動實例化這個類,而不用在第一次調用Instance()後才實例化出惟一的單例對象。 private static readonly Singleton instance = new Singleton(); private Singleton() { } public static Singleton Instance() { return instance; } }