1. 什么是單例
保證一個類只有一個實例的實現方法。
2. 使用場景
頁面訪問計數器
需要保持狀態的工具類
需求很多,不能一一列舉了
3. 實現方
非線程安全
1 /// <summary> 2 /// 單例模式的實現 3 /// </summary> 4 public sealed class Singleton 5 { 6 //定義一個靜態變量來保存類的實例 7 private static Singleton _instance = null; 8 9 //定義私有構造函數,使外界不能創建該類實例 10 private Singleton() 11 { 12 } 13 /// <summary> 14 /// 定義公有方法提供一個全局訪問點,同時你也可以定義公有屬性來提供全局訪問點 15 /// </summary> 16 /// <returns></returns> 17 public static Singleton Instance() 18 { 19 //如果類的實例不存在則創建,否則直接返回 20 if (_instance == null) 21 { 22 _instance = new Singleton(); 23 } 24 return _instance; 25 } 26 }
上面的單例模式的實現在單線程下確實是可以的,但是在多線程環境下會存在兩個線程同時執行if (instance == null)
並且創建兩個不同的實例
簡單線程安全
1 /// <summary> 2 /// 單例模式的實現 3 /// </summary> 4 public sealed class Singleton 5 { 6 // 定義一個靜態變量來保存類的實例 7 private static Singleton instance = null; 8 9 // 定義一個標識確保線程同步 10 private static readonly object padlock = new object(); 11 12 Singleton() 13 { 14 } 15 16 public static Singleton Instance() 17 { 18 // 當第一個線程運行到這里時,此時會對locker對象 "加鎖", 19 // 當第二個線程運行該方法時,首先檢測到locker對象為"加鎖"狀態,該線程就會掛起等待第一個線程解鎖 20 // lock語句運行完之后(即線程運行完之后)會對該對象"解鎖" 21 lock (padlock) 22 { 23 // 如果類的實例不存在則創建,否則直接返回 24 if (instance == null) 25 { 26 instance = new Singleton(); 27 } 28 } 29 return instance; 30 } 31 }
上面的例子解決了多線程的問題,但是每個線程調用Instance()都會使用到鎖,而調用鎖的開銷較大,這個實現會有一定的性能損失。
雙重驗證線程安全
1 /// <summary> 2 /// 單例模式的實現 3 /// </summary> 4 public sealed class Singleton 5 { 6 // 定義一個靜態變量來保存類的實例 7 private static Singleton instance = null; 8 9 // 定義一個標識確保線程同步 10 private static readonly object padlock = new object(); 11 12 Singleton() 13 { 14 } 15 16 public static Singleton Instance() 17 { 18 // 當第一個線程運行到這里時,此時會對locker對象 "加鎖", 19 // 當第二個線程運行該方法時,首先檢測到locker對象為"加鎖"狀態,該線程就會掛起等待第一個線程解鎖 20 // lock語句運行完之后(即線程運行完之后)會對該對象"解鎖" 21 if (instance == null) 22 { 23 lock (padlock) 24 { 25 // 如果類的實例不存在則創建,否則直接返回 26 if (instance == null) 27 { 28 instance = new Singleton(); 29 } 30 } 31 } 32 return instance; 33 } 34 }
上面的例子在保證線程安全的同時提高了性能
靜態變量實現單例
1 /// <summary> 2 /// 單例模式的實現 3 /// </summary> 4 public sealed class Singleton 5 { 6 //在Singleton第一次被調用時會執行instance的初始化 7 private static readonly Singleton instance = new Singleton(); 8 9 private Singleton() 10 { 11 } 12 13 public static Singleton Instance() 14 { 15 return instance; 16 } 17 }
上面的例子利用.net的特性來完成單例模式的創建,也是線程安全的
4. 優點
在內存中只有一個對象,節省內存空間;
避免頻繁的創建銷毀對象,可以提高性能;
避免對共享資源的多重占用,簡化訪問;
為整個系統提供一個全局訪問點。