保證一個類僅有一個實例,並提供一個訪問它的全局訪問點.html
一般咱們可讓一個全局變量使得一個對象被訪問,但它不能防止你實例化多個對象。一個最好的辦法就是讓類自身負責保存它的惟一實例。這個類能夠保證沒有其它實例能夠唄建立而且它能夠提供一個訪問該實例的方法,這就是單例模式。c#
Singleton類定義了一個GetInstance 操做,容許客戶訪問它的惟一實例,GetInstance是一個靜態方法,主要負責建立本身的惟一實例。多線程
public class Singleton { private static Singleton _instance; private Singleton()//私有化構造函數,阻止外界利用new關鍵詞來建立實例 {} public static Singleton GetInstance() { return _instance ?? (_instance = new Singleton()); } }
public void Myaction() { var s1 = Singleton.GetInstance(); var s2 = Singleton.GetInstance(); if (s1 == s2) { Console.WriteLine("兩個對象是相同的!"); } Console.Read(); }
上面的代碼在多線程的程序下運行明細是有問題的,當多個線程同時訪問Singleton類 都調用GetInstance()方法,就有可能會建立多個實例。函數
這種狀況咱們能夠給進程一把鎖來處理,這裏須要理解 lock 語句的涵義,lock 是確保當前一個線程位於代碼的臨界區時,另外一個線程不進入臨界區。若是其它線程試圖進入鎖定的代碼,則它將一直等待(即被阻止),直到該對象被釋放。性能
public class Singleton { private static Singleton _instance; //程序執行時建立一個靜態的只讀的進程輔助對象 private static readonly object SyncRoot = new object(); private Singleton()//私有化構造函數,阻止外界利用new關鍵詞來建立實例 { } public static Singleton GetInstance() { lock (SyncRoot)//在同一時刻加了鎖的那部分程序只有一個線程能夠進入 { _instance= _instance ?? (_instance = new Singleton()); } return _instance; } }
經過上面的例子咱們不難發現當咱們每次調用 GetInstance() 方法時都要 lock 這種作法顯然是影響性能的因此咱們須要再加一層判斷測試
public class Singleton { private static Singleton _instance; //程序執行時建立一個靜態的只讀的進程輔助對象 private static readonly object SyncRoot = new object(); private Singleton()//私有化構造函數,阻止外界利用new關鍵詞來建立實例 {} public static Singleton GetInstance() { if (_instance == null)//先判斷實例是否存在,不存在在枷鎖處理 { lock (SyncRoot)//在同一時刻加了鎖的那部分程序只有一個線程能夠進入 { _instance = _instance ?? (_instance = new Singleton()); } } return _instance; } }
咱們在開發過程當中常常都須要對數據上下文進行單例,因此這裏結合簡單工廠 來實現數據上下文的建立線程
public class DbFactory { private static readonly object SyncRoot=new object(); private DbFactory() {} #region 獲取當前的上下文對象 /// <summary> /// 單例工廠 獲取當前的上下文對象 //考慮多線程狀況 /// </summary> /// <returns></returns> public static SiyoukuContext GetCurrentDbContext() { var context = (SiyoukuContext) CallContext.GetData("DbContext"); //從數據槽獲取 if (context == null) { lock (SyncRoot)//雙重鎖定 { if (context == null) { //若是不存在 ,則實例化一個上下文對象 context = new SiyoukuContext(); CallContext.SetData("DbContext", context); } } } return context; } #endregion }
本文記錄了本身對單例模式的總結htm
博主網址:http://www.siyouku.cn對象
本文永久更細地址:http://siyouku.cn/article/6812.html進程