C# 多线程下的单例模式

在上一篇博客中(https://www.cnblogs.com/t140603/p/10318228.html)提到的第二个单例模式的实例为:

public class SingLetonClass

    {

        //定义一个用于保存静态变量的实例

        private static SingLetonClass instance = null;

        //定义一个保证线程同步的标识

        private static readonly object locker = new object();

        //构造函数为私有,使外界不能创建该类的实例

        private SingLetonClass()

        {

        }

        public static SingLetonClass GetInstance()

        {

                lock (locker)

                {

                    if (instance == null)

                    {

                        SingLetonClass instance = new SingLetonClass();

                    }

                }

            return instance;

        }

    }

然而这个实现方式虽然是安全的,但是是不是最好的呢,还能不能再次进行优化?

下面就分析一下多线程中单例模式的运行:

  当程序的线程执行到锁时,就会停下来判断是否有其他线程在执行锁里面的代码,没有才会进入继续执行,那么如果多条线程同时运行到锁的时候就只能一条一条进入锁,进入并判断是否已被实例化,如有就跳出,如无,则进行实例化。

  上面,我们对多线程中的单例模式进行了分析,从分析中我们可以看出,每条线程都要先进入锁才做判断,但在没进入之前,线程就已经可以判断出是否有过实例,那为什么我们不在外面就先进行判断再进入锁呢?下面就给出优化后的代码:即再锁的外面多加一次判断。

public class SingLetonClass

    {

        //定义一个用于保存静态变量的实例

        private static SingLetonClass instance = null;

        //定义一个保证线程同步的标识

        private static readonly object locker = new object();

        //构造函数为私有,使外界不能创建该类的实例

        private SingLetonClass()

        {

        }

        public static SingLetonClass GetInstance()

        {

            if (instance == null)

              {

                lock (locker)

                {

                    if (instance == null)

                    {

                        SingLetonClass instance = new SingLetonClass();

                    }

                }

            return instance;

          }

        }

}

  从更改后的代码上来看,用了两个if进行判断的原因还是在于多线程的特性,还是因为多线程访问函数时都是独立访问的,所以才要用到两个if(如果对多线程特性不太了解的童鞋,可自行查资料研究一下)。

  先分析内层的if语句块,在这个语句块执行之前,先进行了加锁操作,从而保证只有一个线程能够访问该语句块,也就是保证只创建了一个实例。再分析外层的if语句块,这使得每个线程欲获取实例时不必每次都得加锁,因为只有实例为空时(即需要创建一个实例),才需加锁创建,若果已存在一个实例,就直接返回该实例,这样就节省了性能开销。

  这个过程实际上不是双重锁,只是进行了两次判断,因为真正的锁机制代价是比较高的,所以本文介绍的机制可以称为双检锁机制。

猜你喜欢

转载自www.cnblogs.com/t140603/p/10429018.html
今日推荐