单例模式详解

           设计模式——单例模式

        创建型设计模式一共包括五类设计模式,分别是:单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式。上篇博客中讲到了工厂方法模式,这篇博客就给大家说一下经常用到的单例模式。

单例模式:

    定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

    结构图:

   

         单例模式中就只有这一个类,Singleton类,他的作用是:定义一个GetIntance操作,允许客户访问它的唯一实例。GetInstance是一个静态方法,主要负责创建自己的唯一实例。代码如下:

  

class Singleton
    {
        private static Singleton instace;
        private Singleton ()
        {
        }
        public static Singleton GetInstance()
        {
            if (instace ==null)     //判断是否实例化
            {
                instace = new Singleton();               
            }
            return instace;
        }
    }

    使用单例模式的好处:单例模式因为Singleton封装它的唯一实例,这样它可以严格的控制客户怎样访问它以及何时访问它,简单的说就是对唯一实例的受控访问。

多线程的单例:

     如果在多线程的程序中,多个线程同时访问Singleton类,调用getInstance方法,会有可能创建多个实例的,所以在这里要在程序中加上一把锁:Lock。Lock是确保当一个线程位于代码的临界区时,另一个线程不进入临界区,如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止)直到对象被释放。代码如下:   

class Singleton
    {
        private static Singleton instace;
        private static readonly object syncRoot = new object();    //程序运行时创建一个静态只读的进程辅助对象。
        private Singleton ()
        {

        }
        public static Singleton GetInstance()
        {
            lock (syncRoot )   //在同一时刻加了锁的那部分程序只有一个线程可以进入。
            {
                if (instace == null)  //判断是否实例化
                {
                    instace = new Singleton();

                }
                return instace;
            }
            
        }
    }

      这样可以使得实例对象由最先进入的那个线程创建,以后的线程在进入时不会再去创建对象实例了,由于有了lock,就保证了多线程环境下的同时访问也不会造成多个实例的生成。但是这样的的锁定有一个弊端,就是在每次调用GetInstance时就需要进行一次锁定lock。这样会无形中影响了程序的性能。所以为了解决这个问题,有了下边的双重锁定:

    双重锁定不用让线程每次都加锁,而只是在实例未被创建的时候在加锁处理,同时也能保证多线程的安全。代码如下:

class Singleton
    {
        private static Singleton instace;
        private static readonly object syncRoot = new object();    //程序运行时创建一个静态只读的进程辅助对象。
        private Singleton ()
        {

        }
        public static Singleton GetInstance()
        {
            if (instace ==null)    //第一次判断是否实例化
            {
                lock (syncRoot)   //在同一时刻加了锁的那部分程序只有一个线程可以进入。
                {
                    if (instace == null)      <span style="font-family: Arial, Helvetica, sans-serif;">//第一次判断是否实例化</span>

                    {
                        instace = new Singleton();
                    }                  
                }
            }
            return instace;
        }
    }<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>

     为什么叫双重锁定?因为在对于instance存在的情况下,就直接返回,这样就没有问题,当instance为null并且同时有两个线程同时调用GetInstance()方法时,他们将都可以通过第一重instance==null的判断。然后由于lock机制,这两个线程则只有一个进入,另一个在外排队等候。此时如果没有了第二重的instance判断,则第一个线程创建了实例,而第二个线程还是可以在继续创建新的实例的。

    单例模式是一个很常见的模式,以后我们在做系统的时候回经常用到,好好总结一下,以后用的时候就知道怎么用了。



     

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值