单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
1.不考虑多线程
class Singleton
{
private static Singleton instance;
//private无法new创建此类的实例
private Singleton()
{
}
//此方法是获得本类实例的唯一全局访问点
public static Singleton GetInstance()
{
//若实例不存在,则new一个新的实例
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
2.多线程时的单例
2.1单重锁定
class Singleton2
{
private static Singleton2 instance;
//程序运行时创建一个静态制度的进程辅助对象(加所示,instance实例是否创建未知)
private static readonly Object syncRoot = new Object();
private Singleton2()
{
}
public static Singleton2 GetInstance()
{
//在同一个时刻加锁的那部分程序只有一个进程可以进入
lock (syncRoot)
{
if (instance == null)
{
instance = new Singleton2();
}
}
return instance;
}
}
2.2 双重锁定
class Singleton3
{
private static Singleton3 instance;
private static readonly Object syncRoot = new Object();
private Singleton3()
{
}
public static Singleton3 GetInstance()
{
//先判断实例是否存在,不存在再加锁处理
if (instance == null)
{
lock (syncRoot)
{
if (instance == null) //多个进程第一个判断都通过,一个进入锁定,其余排队等候,否则会创建多个实例
{
instance = new Singleton3();
}
}
}
return instance;
}
}
3.静态初始化
C#和CLR提供的一种方式,不需要编写线程安全代码,即可解决多线程下不安全的问题
/// <summary>
/// 静态初始化
/// </summary>
sealed class Singleton4 //sealed阻止派生,而派生可能会增加实例
{
//第一次引用类的任何成员时创建实例
private static readonly Singleton4 instance = new Singleton4();
private Singleton4()
{
}
public static Singleton4 GetInstance()
{
return instance;
}
}
这种静态初始化的方式是在自己被加载时就将自己实例化,所以被形象地称之为饿汉式单例类
上面3种在第一次引用时才会实例化,所以被称之为懒汉式单例类
总结:
饿汉式在类一加载就实例化,所以要提前占用系统资源;
而懒汉式面临多线程访问的安全性问题,需做双重锁才能保证安全。
所以到底用哪一种取决于实际需求。