保证一个类仅有一个实例,并提供一个访问它的全局访问点。
在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。
public class SingletonTest
{
public static void Test()
{
var tasks = new List<Task>();
for (int i = 0; i < 20; i++)
{
tasks.Add(new Task(() =>
{
Singleton singleton = Singleton.Instance();
singleton.GetData();
}));
}
//并发执行20个任务
tasks.AsParallel().ForAll(p => p.Start());
}
private class Singleton
{
/// <summary>
/// 静态实例,利用静态字段把实例缓存起来
/// </summary>
private static Singleton singleton;
/// <summary>
/// 返回对象的唯一实例
/// </summary>
/// <returns></returns>
public static Singleton Instance()
{
if (singleton == null)
{
Console.WriteLine("实例化对象");
singleton = new Singleton();
}
return singleton;
}
public void GetData()
{
Console.WriteLine("调用了getdata()");
}
}
}
看下执行结果
实例化对象动作执行了4次,说明并发情况下有问题;
改下实现方式,增加锁
public static Singleton Instance()
{
if (singleton == null)
{
lock (lockObj)
{
Console.WriteLine("实例化对象");
singleton = new Singleton();
}
}
return singleton;
}
看下执行结果
依然不能保证
加锁并双重验证
public static Singleton Instance()
{
if (singleton == null)
{
lock (lockObj)
{
if (singleton == null)
{
Console.WriteLine("实例化对象");
singleton = new Singleton();
}
}
}
return singleton;
}
看下执行结果
这下就不会有并发的问题了