當前位置:
首頁 > 知識 > 單例模式,多線程單例,雙重鎖定單例,工廠單例創建上下文

單例模式,多線程單例,雙重鎖定單例,工廠單例創建上下文

單例子模式定義

保證一個類僅有一個實例,並提供一個訪問它的全局訪問點.

通常我們可以讓一個全局變數使得一個對象被訪問,但它不能防止你實例化多個對象。一個最好的辦法就是讓類自身負責保存它的唯一實例。這個類可以保證沒有其它實例可以唄創建並且它可以提供一個訪問該實例的方法,這就是單例模式。

單例子模式簡單實現

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;
}
}

雙重鎖定(Double-Check Locking)

通過上面的例子我們不難發現當我們每次調用 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 獲取當前的上下文對象
///

/// 單例工廠 獲取當前的上下文對象 //考慮多線程情況
///

///
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
}

本文記錄了自己對單例模式的總結

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 達人科技 的精彩文章:

數據應用達人之SQL基礎教程分享13-存儲過程與事務
Redis持久化機制比對

TAG:達人科技 |

您可能感興趣

單例模式的特點
單例模式介紹
js設計模式之一-單例模式
深入理解單例模式 ( 下 )
三種推薦使用的單例模式解析
C++ 單例模式總結與剖析
漫畫:如何給女朋友解釋什麼是單例模式?| 技術頭條
Python 中的單例模式
static 單例模式autoptr與單例模式const 用法小結mutable修飾符