保证一个类仅有一个实例,并提供一个访问它的全局访问点.html
一般咱们可让一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象。一个最好的办法就是让类自身负责保存它的惟一实例。这个类能够保证没有其它实例能够呗建立而且它能够提供一个访问该实例的方法,这就是单例模式。c#
Singleton类定义了一个GetInstance 操做,容许客户访问它的惟一实例,GetInstance是一个静态方法,主要负责建立本身的惟一实例。多线程
public class Singleton { private static Singleton _instance; private Singleton()//私有化构造函数,阻止外界利用new关键词来建立实例 {} public static Singleton GetInstance() { return _instance ?? (_instance = new Singleton()); } }
public void Myaction() { var s1 = Singleton.GetInstance(); var s2 = Singleton.GetInstance(); if (s1 == s2) { Console.WriteLine("两个对象是相同的!"); } Console.Read(); }
上面的代码在多线程的程序下运行明细是有问题的,当多个线程同时访问Singleton类 都调用GetInstance()方法,就有可能会建立多个实例。函数
这种状况咱们能够给进程一把锁来处理,这里须要理解 lock 语句的涵义,lock 是确保当前一个线程位于代码的临界区时,另外一个线程不进入临界区。若是其它线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。性能
public class Singleton { private static Singleton _instance; //程序执行时建立一个静态的只读的进程辅助对象 private static readonly object SyncRoot = new object(); private Singleton()//私有化构造函数,阻止外界利用new关键词来建立实例 { } public static Singleton GetInstance() { lock (SyncRoot)//在同一时刻加了锁的那部分程序只有一个线程能够进入 { _instance= _instance ?? (_instance = new Singleton()); } return _instance; } }
经过上面的例子咱们不难发现当咱们每次调用 GetInstance() 方法时都要 lock 这种作法显然是影响性能的因此咱们须要再加一层判断测试
public class Singleton { private static Singleton _instance; //程序执行时建立一个静态的只读的进程辅助对象 private static readonly object SyncRoot = new object(); private Singleton()//私有化构造函数,阻止外界利用new关键词来建立实例 {} public static Singleton GetInstance() { if (_instance == null)//先判断实例是否存在,不存在在枷锁处理 { lock (SyncRoot)//在同一时刻加了锁的那部分程序只有一个线程能够进入 { _instance = _instance ?? (_instance = new Singleton()); } } return _instance; } }
咱们在开发过程当中常常都须要对数据上下文进行单例,因此这里结合简单工厂 来实现数据上下文的建立线程
public class DbFactory { private static readonly object SyncRoot=new object(); private DbFactory() {} #region 获取当前的上下文对象 /// <summary> /// 单例工厂 获取当前的上下文对象 //考虑多线程状况 /// </summary> /// <returns></returns> public static SiyoukuContext GetCurrentDbContext() { var context = (SiyoukuContext) CallContext.GetData("DbContext"); //从数据槽获取 if (context == null) { lock (SyncRoot)//双重锁定 { if (context == null) { //若是不存在 ,则实例化一个上下文对象 context = new SiyoukuContext(); CallContext.SetData("DbContext", context); } } } return context; } #endregion }
本文记录了本身对单例模式的总结htm
博主网址:http://www.siyouku.cn对象
本文永久更细地址:http://siyouku.cn/article/6812.html进程