单例模式只允许被其自身实例化一次,且向外部提供了一个访问该实例的接口。

以下所有方法均通过public static Instance属性获取单例类实例。

实例检测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public sealed class Singleton
{
private static Singleton instance = null;
private Singleton() { }
public static Singleton Instance
{
get
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
}

该方法在多线程下可能创建多个实例。当多个线程同时运行到if(instance==null)时,将在每个线程均生成一个实例。

不建议使用。

增加锁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public sealed class Singleton
{
private static Singleton instance = null;
private static readonly object obj = new object();
private Singleton() { }
public Singleton Instance
{
get
{
lock (obj)
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
}
}

在同一时刻只有一个线程在执行lock{}里的代码。但每次获取instance都会加一次锁。

两次实例检测并加锁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public sealed class Singleton
{
private static Singleton instance = null;
private static object obj = new object();
private Singleton() { }
public static Singleton Instance
{
get
{
if (instance == null)
{
lock (obj)
{
if (instance == null)
{
instance = new Singleton();
}
}
}
return instance;
}
}
}

尽量减少锁操作,至少在同一线程内获取实例时不需要加锁了。

静态构造函数

1
2
3
4
5
6
7
public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();
static Singleton() { }
private Singleton() { }
public static Singleton Instance { get { return instance; } }
}

这是一种懒汉式初始化。C#的静态构造函数只有在当第一次被实例化或者第一次静态成员被引用时执行,且在整个应用程序域中只会被执行一次。简单又快速。

但如果有其他与该类内与其实例无关的静态方法被引用时也会对其进行初始化,并不是真正意义上的懒汉式。

该方法简单易懂,满足大多数场景要求。

懒汉式

1
2
3
4
5
6
7
8
9
10
public sealed class Singleton
{
private Singleton() { }
public static Singleton Instance { get { return Nested.instance; } }
private class Nested
{
static Nested() { }
internal static readonly Singleton instance = new Singleton();
}
}

修复静态构造函数式懒加载的不足。使用内嵌类实现只有在真正用到该实例时才进行实例化。

Lazy类

1
2
3
4
5
6
7
public sealed class Singleton
{
private static readonly Lazy<Singleton> lazy =
new Lazy<Singleton>(()=> new Singleton());
public static Singleton Instance { get { return lazy.Value; } }
private Singleton() { }
}

直接使用System.Lazy实现懒汉式。