zoukankan      html  css  js  c++  java
  • C# 单例模式的多种简单实现

    C# 单例模式的多种简单实现

    什么是单例模式?

    这里我就不做过多的解释了, 毕竟关于Singleton的资料实在是太多太多了。点击这里

    1.简单的思路就是, 创建对象单例的动作转移到另外的行为上面, 利用一个行为去创建对象自身, 如下: 

       public class Singleton
        {
            private static Singleton _Singleton = null;
            public static Singleton CreateInstance()
            {
                if (_Singleton == null)
                {
                 Console.WriteLine("被创建");
                 _Singleton = new Singleton();
                }
                return _Singleton;
            }
        }

    这样写看上去是没有问题, 但是有没有那种可能, 同时两个动作都判断这个对象为空, 那么这个对象就会被创建2次?是的, 多线程中, 这样是无法保证单例。

    就像这样, 同时创建多个线程去创建这个对象实例的时候, 会被多次创建, 这个时候, 对代码改进一下。

        public class Singleton
        {
            private static Singleton _Singleton = null;
            private static object Singleton_Lock = new object(); //锁同步
            public static Singleton CreateInstance()
            {
                    lock (Singleton_Lock)
                    {
                Console.WriteLine("路过");
                        if (_Singleton == null)
                        {
                  Console.WriteLine("被创建");
                            _Singleton = new Singleton();
                        }
                    }
                return _Singleton;
            }
        }

    调试代码:

                   TaskFactory taskFactory = new TaskFactory();
                    List<Task> taskList = new List<Task>();
    
                    for (int i = 0; i < 5; i++)
                    {
                        taskList.Add(taskFactory.StartNew(() =>
                         {
                             Singleton singleton = Singleton.CreateInstance(); 
                         }));
                    }

    结果:

    上面, 我们创建了多个线程,同时去创建这个对象的实例, 在第二次,对象命名已经被创建了, 尽管只创建了一次满足了我们的需求, 但是我们已知对象被创建了, 还需要进来做不必要的动作吗?

    我们都知道, 同步锁为了达到预期的效果, 也是损耗了性能的, 那么下面的输出, 很显然是没必要的动作, 所以我们优化一下。

        public class Singleton
        {
            private static Singleton _Singleton = null;
            private static object Singleton_Lock = new object();
            public static Singleton CreateInstance()
            {
                if (_Singleton == null) //双if +lock
                {
                    lock (Singleton_Lock)
                    {
                        Console.WriteLine("路过。");
                        if (_Singleton == null)
                        {
                            Console.WriteLine("被创建。");
                            _Singleton = new Singleton();
                        }
                    }
                }
                return _Singleton;
            }
        }

    结果:

    很显然, 这样达到了我们的预期, 对象在被创建后, 就没必要做多余的行为。

    利用静态变量实现单例模式

        public class SingletonThird
        {
            /// <summary>
            /// 静态变量
            /// </summary>
            private static SingletonThird _SingletonThird = new SingletonThird();
            
            public static SingletonThird CreateInstance()
            {
                return _SingletonThird;
            }
        }

    是不是觉得很优雅, 利用静态变量去实现单例,  由CLR保证,在程序第一次使用该类之前被调用,而且只调用一次

    PS: 但是他的缺点也很明显, 在程序初始化后, 静态对象就被CLR构造了, 哪怕你没用。

    利用静态构造函数实现单例模式

        public class SingletonSecond
        {
            private static SingletonSecond _SingletonSecond = null;
    
            static SingletonSecond()
            {
                
                _SingletonSecond = new SingletonSecond();
            }
            
            public static SingletonSecond CreateInstance()
            {
                return _SingletonSecond;
            }
        }

    静态构造函数:只能有一个,无参数的,程序无法调用 。

    同样是由CLR保证,在程序第一次使用该类之前被调用,而且只调用一次

    同静态变量一样, 它会随着程序运行, 就被实例化, 同静态变量一个道理。

    何谓生死、功名利禄、皆为浮云

  • 相关阅读:
    tyvj 1031 热浪 最短路
    【bzoj2005】 [Noi2010]能量采集 数学结论(gcd)
    hdu 1394 Minimum Inversion Number 逆序数/树状数组
    HDU 1698 just a hook 线段树,区间定值,求和
    ZeptoLab Code Rush 2015 C. Om Nom and Candies 暴力
    ZeptoLab Code Rush 2015 B. Om Nom and Dark Park DFS
    ZeptoLab Code Rush 2015 A. King of Thieves 暴力
    hdoj 5199 Gunner map
    hdoj 5198 Strange Class 水题
    vijos 1659 河蟹王国 线段树区间加、区间查询最大值
  • 原文地址:https://www.cnblogs.com/grj001/p/12225494.html
Copyright © 2011-2022 走看看