(C#程式碼演示)常用的兩種單例模式--餓漢式和懶漢式
阿新 • • 發佈:2020-08-11
一.餓漢式
在程式開始時,該類就建立了例項了,但可能在執行時沒有呼叫,造成不必要的消耗
程式碼:
1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4
5 namespace 設計模式
6 {
7 class 單例Singleton1
8 {
9 private static 單例Singleton1 R = new 單例Singleton1();
10 private 單例Singleton1()
11 { }
12
13 public static 單例Singleton1 Return單例Singleton例項()
14 {
15 return R;
16 }
17 }
18 }
二.懶漢式
只有在呼叫Return單例Singleton例項()方法時才會例項化該類,解決了可能的發生效能消耗問題,但是在多執行緒測試時出現了問題------多執行緒不安全,可以看到控制檯中輸出的HashCode一開始時不同的
這是由於 執行緒1執行到時,而3執行緒2執行到,由於R還是null,所有執行緒2還會執行if中的語句,造成執行緒出錯的問題
程式碼:
1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using System.Threading;
5
6 namespace 設計模式
7 {
8 class 單例Singleton2
9 {
10 private static 單例Singleton2 R;
11 private 單例Singleton2()
12 { }
13
14 public static 單例Singleton2 Return單例Singleton例項()
15 {
16 if (R == null)
17 {
18 Thread.Sleep(3);//模擬程式延遲
19 R = new 單例Singleton2();
20 }
21 return R;
22 }
23 }
24 }
多執行緒安全測試
程式碼:
1 using System;
2 using System.Threading;
3
4 namespace 設計模式
5 {
6 class Program
7 {
8 static void Main(string[] args)
9 {
10 for (int i = 0; i < 100; i++)
11 {
12 Thread thread = new Thread(a);
13 thread.Start();
14 }
15 }
16 static void a()
17 {
18 單例Singleton2 a = 單例Singleton2.Return單例Singleton例項();
19 Console.WriteLine(a.GetHashCode());
20 }
21 }
22 }
測試結果:
輸出新執行緒中的 例項的HashCode,很顯然是不安全的
三.懶漢式 執行緒問題完善
雙重if可以減小lock()方法的使用,從而減小消耗
程式碼:
1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4
5 namespace 設計模式
6 {
7 class 單例Singleton3
8 {
9 private static readonly object syncRoot = new object(); // 定義一個標識確保執行緒同步
10 private static 單例Singleton3 R;
11 private 單例Singleton3()
12 { }
13
14 public static 單例Singleton3 Return單例Singleton例項()
15 {
16 if (R == null)//雙重檢測 減小消耗
17 {
18 // 當第一個執行緒執行到這裡時,此時會對locker物件 "加鎖",
19 // 當第二個執行緒執行該方法時,首先檢測到locker物件為"加鎖"狀態,該執行緒就會掛起等待第一個執行緒解鎖
20 // lock語句執行完之後(即執行緒執行完之後)會對該物件"解鎖"
21 lock (syncRoot)
22 {
23 if (R == null)//雙重檢測 減小消耗
24 {
25 R = new 單例Singleton3();
26 }
27
28 }
29 }
30 return R;
31 }
32 }
33 }
我們再輸出一下每個執行緒中的例項的HashCode