一.饿汉式

在程序开始时,该类就创建了实例了,但可能在运行时没有调用,造成不必要的消耗

代码:

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执行到

java饿汉式和懒汉式 饿汉式代码_System

时,而3线程2执行到

java饿汉式和懒汉式 饿汉式代码_设计模式_02

,由于R还是null,所有线程2还会执行if中的语句,造成线程出错的问题

java饿汉式和懒汉式 饿汉式代码_多线程_03

代码:

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,很显然是不安全的

java饿汉式和懒汉式 饿汉式代码_System_04

 

 

 三.懒汉式 线程问题完善

双重if可以减小lock()方法的使用,从而减小消耗

java饿汉式和懒汉式 饿汉式代码_多线程_05

 

 代码:

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

java饿汉式和懒汉式 饿汉式代码_多线程_06