ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

单例模式:进程唯一。

2021-09-30 11:04:08  阅读:110  来源: 互联网

标签:Instance 模式 instance static private 单例 进程 线程 public


单例模式:进程唯一。

  • 非线程安全。

    public sealed class SingletonV1
    {
        private static SingletonV1 instance = null;
    
        private SingletonV1()
        {
        }
    
        public static SingletonV1 Instance
        {
            get
            {
                if (instance == null) // -> 1
                { // -> 2
                    instance = new SingletonV1();
                }
    
                return instance;
            }
        }
    }
    

    假设:首次访问,同一时间,有N(N>=2)个线程同时访问单例。

    解:

    1. 实例并未创建,所有线程都能进入创建实例代码块。
    2. N个线程使用的实例不相同。

    注:违反了单例的唯一性原则。

  • 简单线程安全。

    public sealed class SingletonV2
    {
        private static SingletonV2 instance = null;
        private static readonly object padlock = new object();
    
        SingletonV2()
        {
        }
    
        public static SingletonV2 Instance
        {
            get
            {
                lock (padlock) // -> 1
                {
                    if (instance == null)
                    {
                        instance = new SingletonV2();
                    }
                    return instance;
                }
            }
        }
    }
    

    假设:同一时间,有N(N>=2)个线程同时访问单例。

    解:由于lock是悲观锁,导致获取单例变成了单线程操作。

    注:单线程的代码块,会严重降低多线程的性能。

  • 双重检查线程安全。

    public sealed class SingletonV3
    {
        private static SingletonV3 instance = null;
        private static readonly object padlock = new object();
    
        SingletonV3()
        {
        }
    
        public static SingletonV3 Instance
        {
            get
            {
                if (instance == null) // -> 1
                {
                    lock (padlock)
                    {
                        if (instance == null) // -> 2
                        {
                            instance = new SingletonV3();
                        }
                    }
                }
                return instance;
            }
        }
    }
    

    解:

    1. 第一层检查的意义:当实例被创建后,不再进入锁。
    2. 第二层检查的意义:并发时,可能有多个线程躲过了第一层检查,在锁内部判断,确保仅有一个线程创建实例。

    注:只有实例未被创建之前的调用是单线程。

  • 非懒惰线程安全。

    public sealed class SingletonV4
    {
        private static readonly SingletonV4 instance = new SingletonV4(); // -> 1
    
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static SingletonV4()
        {
        }
    
        private SingletonV4()
        {
        }
    
        public static SingletonV4 Instance
        {
            get
            {
                return instance;
            }
        }
    }
    

    解:单例会在首次触发静态属性/方法时,生成实例。

    注:若类中存在静态属性/方法时,调用静态属性/方法也会创建实例,导致单例提前工作。

  • 推荐完全懒惰线程安全。

    public sealed class SingletonV5
    {
        private SingletonV5()
        {
        }
    
        public static SingletonV5 Instance { get { return Nested.instance; } } // -> 1
    
        private class Nested
        {
            // Explicit static constructor to tell C# compiler
            // not to mark type as beforefieldinit
            static Nested()
            {
            }
    
            internal static readonly SingletonV5 instance = new SingletonV5(); 
        }
    }
    

    注:仅在首次使用【SingletonV5.Instance】时,会创建实例。

  • 懒加载线程安全。

    public sealed class SingletonV6
    {
        private static readonly Lazy<SingletonV6> lazy =
            new Lazy<SingletonV6>(() => new SingletonV6());
    
        public static SingletonV6 Instance { get { return lazy.Value; } }
    
        private SingletonV6()
        {
        }
    }
    

    注:使用懒加载,保证所有线程使用的实例相同,但并一定只会初始化一次实例。

    引用:

  • 强力推荐完全懒惰线程安全--反射。

    public class SingletonV7<T> where T : class
    {
        static SingletonV7() { }
    
        public static T Instance => Nested.Instance;
    
        private static class Nested
        {
            static Nested() { }
    
            public static readonly T Instance = (T)Activator.CreateInstance(typeof(T), true); // -> 1
        }
    }
    

    解:

    1. 作为基类。

      定义:继承SingletonV7<T>,其中T是需要作为单例的类。

      public sealed class Singleton : SingletonV7<Singleton>
      {
          private Singleton() { }
          
          public int Add(int i, int j) => i + j;
      }
      

      用法:

      int value = Singleton.Instance.Add(1, 2);
      
    2. 作为工具类。

      定义:任意包含(公共/私有)无参构造函数的类。

      public sealed class Singleton
      {
          private Singleton() { }
          
          public int Add(int i, int j) => i + j;
      }
      

      用法:

      int value = Singleton.Instance.Add(1, 2);
      

标签:Instance,模式,instance,static,private,单例,进程,线程,public
来源: https://www.cnblogs.com/tsia/p/15355787.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有