初识
单例模式(Singleton),保证一个类仅有一个实例,并提供一个访问它的全局访问点。是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的一个类只有一个实例。即一个类只有一个对象实例。
结构
角色:
Singleton类:定义一个GetInstance操作,允许客户访问它的唯一实例,GetInstance是一个静态方法,主要负责创建自己的唯一实例。
多线程单例
代码实现
class Program
{
static void Main(string[] args)
{
Singleton s1 = Singleton.GetInstance();
Singleton s2 = Singleton.GetInstance();
if (s1 == s2)
{
Console.WriteLine("两个对象是相同的实例");
}
Console.Read();
}
}
class Singleton
{
private static Singleton instance;
private static readonly object syncRoot = new object();//程序运行时创建的静态只读的进程辅助对象
private Singleton()//堵死了外界创建此类实例的可能
{
}
public static Singleton GetInstance()
{
if (instance == null)//判断实例是否存在
{
lock (syncRoot)//加锁,防止多线程同时进入临界区
{
if (instance == null)//双重判断
{
instance = new Singleton();
}
}
}
return instance;
}
}
饿汉式与懒汉式
饿汉式单例类,静态初始化的方式是在自己被加载时就将自己实例化,所以被形象的称之为饿汉式单例类。由于在加载时就将自己实例化了,所以要提前占用系统资源。
//懒汉式单例类
public sealed class Singleton//sealed:防止发生派生,派生可能会增加实例
{
private static readonly Singleton instance = new Singleton();//在加载时便实例化
private Singleton()
{
}
public static Singleton GetSingleton()
{
return instance;
}
}
然而懒汉式单例类,又会面临着多线程访问的安全性问题,需要做双重锁定这样的处理才可以保证安全。(见上面多线程实例代码)
至于使用哪一种方式的单例类,还要取决于实际的需求。从C#语言角度来讲,饿汉式的单例类已经足够满足我们的需求了。
优、缺点
饿汉式单例类:
优点:实现起来简单,没有多线程同步问题。
缺点:当类SingletonTest被加载的时候,会初始化static的instance,静态变量被创建并分配内存空间,从这以后,这个static的instance对象便一直占着这段内存(即便你还没有用到这个实例),当类被卸载时,静态变量被摧毁,并释放所占有的内存,因此在某些特定条件下会耗费内存。
懒汉式单例类:
优点:单例模式的最佳实现方式。内存占用率高,效率高,线程安全,多线程操作原子性。