【单例模式】Singleton pattern_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > 【单例模式】Singleton pattern

【单例模式】Singleton pattern

 2014/7/31 21:17:57  Eric Guo  程序员俱乐部  我要评论(0)
  • 摘要:前言:有很多时候,在一个生命周期中我们只要一个对象就可以了,比如:线程池,缓存,对话框,日志,显卡驱动等等。如果造出多个实例,就会导致许多问题产生,例如:程序的行为异常、资源使用过量,或者说不一致的结果。publicclassSingleton{privatestaticSingletoninstance;privateObject_synchronizedObj=newObject();//privateconstructorprivateSingleton(){
  • 标签:模式 单例模式

前言:有很多时候,在一个生命周期中我们只要一个对象就可以了,比如:线程池,缓存,对话框,日志,显卡驱动等等。如果造出多个实例,就会导致许多问题产生,例如:程序的行为异常、资源使用过量,或者说不一致的结果。

class="code_img_closed" src="/Upload/Images/2014073121/0015B68B3C38AA5B.gif" alt="" />logs_code_hide('35798c08-7ee3-42aa-9009-712cbf70a37f',event)" src="/Upload/Images/2014073121/2B1B950FA3DF188F.gif" alt="" />
public class Singleton
    {
        private static Singleton instance;
        private Object _synchronizedObj = new Object();

        //private constructor
        private Singleton() { }
       

        public Singleton GetInstance
        {
            get
            {
                if (instance == null)
                    lock (_synchronizedObj)
                    {
                        if (instance == null)
                            instance = new Singleton();
                    }
                return instance;
            }
        }
    }
View Code

 

这里用到了Lock, 我看过大部分代理都没有使用到这里,但是如果不用上,在有多线程的项目中就会出现问题。

我用了两次NULL的判断,最外层说因为如果你第一次创建好了就不需要去进行LOCK,这里会有消耗。里面那一个NULL判断是因为如果你有多个线程一起来创建,都通过第一层NULL限制,进入了LOCK等待,当第一个对象创建完,放开了LOCK,第二进去以后,如果不加判断又会创建一次。

 

有人和我说这样会不会更优雅,因为不用一个成员变量Object.

 1  public class Singleton
 2     {
 3         private static Singleton instance;
 4 
 5         //private constructor
 6         private Singleton() { }
 7 
 8 
 9         public Singleton GetInstance
10         {
11             get
12             {
13                 if (instance == null)
14                     lock (typeof(Singleton)) //here
15                     {
16                         if (instance == null)
17                             instance = new Singleton();
18                     }
19                 return instance;
20             }
21         }
22     }
View Code


这里不得不提及 同步索引块(Sync block index),这个东西被关注的特别少,既然说学习CLR,这个东西可是叱咤风云(不过大部分的时候,你不会用而已啦).

Sync block index 初始化和过程

  

当CLR初始化的时候,CLR会初始化一个SyncBlock的数组,当一个线程到达Monitor.Enter方法时,该线程会检查该方法接受的参数的同步块索引,默认情况下对象的同步块索引是一 个负数
(实际上并不是负数,我这里只是为了叙说方便),那么表明该对象并没有一个关联的同步块,CLR就会在全局的SyncBlock数组里找到一个空闲的项,然后将数组的索引赋值给该对象的同步块索
引,当Monitor.Enter执行时,它会设置SyncBlock里的内容,标识出已经有一个线程占用了,当另外一个线 程进入时,它就会检查SyncBlock的内容,发现已经有一个线程占用了,该线程就
会等待,当Monitor.Exit执行时,占用的线程就会释放SyncBlock,其他的线程可以进入操作了。

注:参考博客园另一篇文章:http://www.cnblogs.com/qianyz/archive/2011/10/26/2224925.html(若要了解更多的SyncBlockIndex的用途和原理,可以看这篇)

 所以对于上面的代码:

  typeof(Singleton)返回一个Type对象,如果用这个,会返回相同TYPE对象。我们在这里用lock(typeof(Singleton))锁定了,相当于锁定返回的TYPE对象。OK,当我们在其他在用lock(typeof(Singleton))的时候,又锁了这个对象...2个地方锁了用了同一个对象,结果不该等待的地方也在等待了。 所以我们这里用了私有的Object对象来充当关联进索引块的对象,无论外面这么锁,都锁不住者里东西。

  

发表评论
用户名: 匿名