首页 > 代码库 > 单例模式完整解析

单例模式完整解析

volatile, static readonly, double check

直到对象要求产生一个实例才执行实例化;这种方法称为"懒实例化"。懒实例化避免了在应用程序启动时实例化不必要的 singleton

1. 

using System; public class Singleton {    private static Singleton instance;    private Singleton() {}    public static Singleton Instance    {       get        {          if (instance == null)          {             instance = new Singleton();          }          return instance;       }    } }

但是,这种实现的主要缺点是在多线程环境下它是不安全的。如果执行过程的不同线程同时进入 Instance 属性方法,那么可能会创建多个 Singleton 对象实例。每个线程都会执行下列语句,并决定必须创建新的实例:

if (instance == null) 

解决此问题的方法有很多。一种方法是使用被称为 Double-Check Locking [Lea99] 的技术。而 C# 与公共语言运行库也提供了一种"静态初始化"方法,这种方法不需要开发人员显式地编写线程安全代码,即可解决这些问题。

 

2.  C# 与公共语言运行库提供的"静态初始化"方法

One of the reasons Design Patterns [Gamma95] 避免使用静态初始化的原因之一是,C++ 规范在静态变量的初始化顺序方面留下了一些多义性。幸运的是,.NET Framework 通过其变量初始化处理方法解决了这种多义性:

public sealed class Singleton {    private static readonly Singleton instance = new Singleton();    private Singleton(){}    public static Singleton Instance    {       get        {          return instance;        }    } } 

 

3. Double-Check Locking方法

用volatile修饰instance, 只有实例变量instance分配完,其他线程才能访问它,多线程读它的时候要么是null,要么是完整的分配好的对象。

lock的对象是private的object对象,不要lock公有的对象比如this,type,以免发生死锁。

using System; public sealed class Singleton {    private static volatile Singleton instance;    private static object syncRoot = new Object();    private Singleton() {}    public static Singleton Instance    {       get        {          if (instance == null)           {             lock (syncRoot)              {                if (instance == null)                    instance = new Singleton();             }          }          return instance;       }    } }

此 double-check locking 方法解决了线程并发问题,同时避免在每个 Instance 属性方法的调用中都出现独占锁定。这里的避免独占锁定是不需要锁定整个Instance属性方法,性能不受影响。它还允许您将实例化延迟到第一次访问对象时发生。实际上,应用程序很少需要这种类型的实现。大多数情况下,静态初始化方法已经够用。

优点:Double-Check Locking 技术已在公共语言运行库中正确实现。但是其他环境中还是会有一些常见的、与使用 Double-Check Locking 有关的问题。

 

总结:

最后还是推荐用"静态初始化"方法实现Singleton。实现简单,实现依赖于CLR框架解决多线程问题。

 

参考文章:

http://msdn.microsoft.com/zh-cn/library/ff650316.aspx

http://msdn.microsoft.com/zh-cn/library/ms954629.aspx

http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

单例模式完整解析