using System;
using System.Collections.Generic;
/// <summary>
/// 適用於在多線程的情況下保證只有一個實例化對象的情況,例如銀行的操作系統
/// </summary>
namespace DoubleLockInstance
{
//----------------------------------
// 雙重鎖定單例
public sealed class Singleton
{
// 定義一個類對象,用於內部實現
private static Singleton myInstance;
// readonly - 這個成員只能在“類初始化”時賦值 ,所謂的類初始化,就是直接在類裏面初始化
// 變量標記爲 readonly,第一次引用類的成員時創建實例
private static readonly object lockRoot = new object ();
// 設置構造方法爲私有,這樣就不能在外部實例化類對象了
private Singleton ()
{
}
// 實例化對象的方法
public static Singleton GetInstance ()
{
// 外部不能實例化對象,但是能調用類裏面的靜態方法
// 外部需要調用這個方法來使用類對象,如果對象不存在就創建
// 這裏面使用兩個判斷是否爲null的原因是,我們不需要每次都對實例化的語句進行加鎖,只有當對象不存在的時候加鎖就可以了
if (myInstance == null) {
// 鎖定的作用就是爲了保證當多線程同時執行這句代碼的時候保證對象的唯一性
// 鎖定會讓同時執行這段代碼的線程排隊執行
// lock裏面需要用一個已經存在的對象來判斷,所以不能使用myInstance
lock (lockRoot) {
// 這裏還需要一個判斷的原因是,如果多線程都通過了外層的判斷進行排隊
// 那將會實例化多個對象出來,所以這裏還需要進行一次判斷,保證線程的安全
if (myInstance == null) {
myInstance = new Singleton ();
}
}
}
return myInstance;
}
}
}
百度上看到的實例:
你好!以下是標準的Singleton pattern with Double-check lock。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
public class SingletonClass { private static readonly object _lock = new object (); private static volatile SingletonClass _instance; public static SingletonClass Instance { get { if (_instance == null ) { lock (_lock) { if (_instance == null ) { _instance = new SingletonClass(); } } } return _instance; } } private SingletonClass() { //your constructor } } |
如果你的.NET在4.0以上,可以藉助Lazy<T>泛型更優雅的實現單例模式:
1
2
3
4
5
6
7
8
9
|
public class LazySingleton { private static readonly Lazy<LazySingleton> _instance = new Lazy<LazySingleton>(() => new LazySingleton()); private LazySingleton() { //your constructor } public static LazySingleton Instance { get { return _instance.Value; } } } |