1
using
System;
2
3 namespace Singleton
4 {
5 class Program
6 {
7 static void Main( string [] args)
8 {
9 Singleton s1 = Singleton.Instance;
10 Singleton s2 = Singleton.Instance;
11
12 Console.WriteLine( object .ReferenceEquals(s1, s2));
13
14 Console.Read();
15 }
16 }
17
18
19
20 // 线程安全的单件写法
21 sealed class Singleton // sealed并非必要,看需求而定
22 {
23 private Singleton() { } // 私有构架器的目的是为了防止编译器自动创建默认的公用构架器(从而阻止了用户new类的实例)
24
25 private static volatile Singleton _instance; // valatile关键字用于声明该代码不会被编译器自动优化,从而更严格的保证了单件的实现
26
27 private static object _lockHelper = new object (); // 同步锁辅助对象
28
29 // 定义一个只读实例属性
30 public static Singleton Instance
31 {
32 get
33 {
34 if (_instance == null ) // 初次检测,以防止多次创建实例
35 {
36 // #1
37 lock (_lockHelper) // 多线程环境下,极有可能多个线程“同时”运行到这里,所以如果不用同步锁,有可能会出现多个线程“同时”创建多个实例
38 {
39 if (_instance == null ) // 二次检查以防止创建多个实例(解释:如果不加此句,假设有二个线程同时进入#1处,第一个线程锁定-->创建实例-->解锁 到达#2处,第二个线程还留在#1处,同样还是会创建第二个实例,换言之:加锁的目的是为了防止多个线程同时创建,让线程强制有先后顺序,然后用二次检查来防止重复创建
40 {
41 _instance = new Singleton();
42 }
43 }
44 // #2
45 }
46 return _instance;
47 }
48 }
49 }
50
51
52 #region // 这是c#语言中特有的优雅实现方式
53 // sealed class Singleton // sealed并非必要,看需求而定
54 // {
55 // public static readonly Singleton Instance = new Singleton();
56
57 // private Singleton() { }
58 // }
59
60 // 上面的代码等同于
61
62 // sealed class Singleton
63 // {
64 // public static readonly Singleton Instance; // 因为静态属性初始化后,仍然有可能被赋值修改,所以必须加上readonly以保证单件实例不再被修改的初衷
65
66 // static Singleton() // 静态构造器,会在静态成员初次访问前被调用,同时编译器会自动给静态构造器加锁/解锁,所以该方法同样适合于多线程(线程安全)
67 // {
68 // Instance = new Singleton();
69 // }
70
71 // private Singleton() { }
72 // }
73 #endregion
74 }
75
2
3 namespace Singleton
4 {
5 class Program
6 {
7 static void Main( string [] args)
8 {
9 Singleton s1 = Singleton.Instance;
10 Singleton s2 = Singleton.Instance;
11
12 Console.WriteLine( object .ReferenceEquals(s1, s2));
13
14 Console.Read();
15 }
16 }
17
18
19
20 // 线程安全的单件写法
21 sealed class Singleton // sealed并非必要,看需求而定
22 {
23 private Singleton() { } // 私有构架器的目的是为了防止编译器自动创建默认的公用构架器(从而阻止了用户new类的实例)
24
25 private static volatile Singleton _instance; // valatile关键字用于声明该代码不会被编译器自动优化,从而更严格的保证了单件的实现
26
27 private static object _lockHelper = new object (); // 同步锁辅助对象
28
29 // 定义一个只读实例属性
30 public static Singleton Instance
31 {
32 get
33 {
34 if (_instance == null ) // 初次检测,以防止多次创建实例
35 {
36 // #1
37 lock (_lockHelper) // 多线程环境下,极有可能多个线程“同时”运行到这里,所以如果不用同步锁,有可能会出现多个线程“同时”创建多个实例
38 {
39 if (_instance == null ) // 二次检查以防止创建多个实例(解释:如果不加此句,假设有二个线程同时进入#1处,第一个线程锁定-->创建实例-->解锁 到达#2处,第二个线程还留在#1处,同样还是会创建第二个实例,换言之:加锁的目的是为了防止多个线程同时创建,让线程强制有先后顺序,然后用二次检查来防止重复创建
40 {
41 _instance = new Singleton();
42 }
43 }
44 // #2
45 }
46 return _instance;
47 }
48 }
49 }
50
51
52 #region // 这是c#语言中特有的优雅实现方式
53 // sealed class Singleton // sealed并非必要,看需求而定
54 // {
55 // public static readonly Singleton Instance = new Singleton();
56
57 // private Singleton() { }
58 // }
59
60 // 上面的代码等同于
61
62 // sealed class Singleton
63 // {
64 // public static readonly Singleton Instance; // 因为静态属性初始化后,仍然有可能被赋值修改,所以必须加上readonly以保证单件实例不再被修改的初衷
65
66 // static Singleton() // 静态构造器,会在静态成员初次访问前被调用,同时编译器会自动给静态构造器加锁/解锁,所以该方法同样适合于多线程(线程安全)
67 // {
68 // Instance = new Singleton();
69 // }
70
71 // private Singleton() { }
72 // }
73 #endregion
74 }
75
Singleton的精髓在于:对于类的实例个数做了限制,只要领会了这一点,可以应用到很多场景,比如聊天室最多只能让100个人进来,数据库连接实例只能有200个...