一.饿汉式
在程序开始时,该类就创建了实例了,但可能在运行时没有调用,造成不必要的消耗
代码:
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