定义

单例模式(Singleton Design Pattern)是一种创建型设计模式,它能够保证一个类只有一个实例,并提供一个访问该实例的全局节点。

三个必要条件:

  • 构造函数必须是私有的,保证类的外部不能创建类的实例。
  • 通过一个私有的静态变量来存储其唯一实例。
  • 通过提供一个公开的静态方法,使得外部使用者可以访问类的唯一实例。

三个必要问题:

  • 是否线程安全
  • 是否延时加载
  • 是否需要加锁(锁会导致低性能)

实现

版本一:懒汉式(不推荐)

线程安全 延迟加载 加锁
创建对象时未加锁,获取对象时未加锁
public sealed class Singleton
    {
        private static Singleton _instance = null;

        private Singleton()
        {

        }

        public static Singleton Instance
        {
            get
            {
                if (_instance == null)
                {
                    _instance = new Singleton();
                }
                return _instance;
            }
        }
    }

版本二:懒汉式(一般推荐)

线程安全 延迟加载 加锁
创建对象时加锁,获取对象时加锁
 public sealed class Singleton
    {
        private static Singleton _instance = null;
        private static readonly object InstanceLock = new();

        private Singleton()
        {

        }

        public static Singleton Instance
        {
            get
            {
                lock (InstanceLock)
                {
                    if (_instance == null)
                    {
                        _instance = new Singleton();
                    }
                    return _instance;
                }
            }
        }
    }

版本三:双重检测(不推荐,不如版本五)

线程安全 延迟加载 加锁
创建对象时加锁,获取对象时未加锁
public sealed class Singleton
    {
        private static Singleton _instance = null;
        private static readonly object InstanceLock = new object();

        private Singleton()
        {

        }

        public static Singleton Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (InstanceLock)
                    {
                        if (_instance == null)
                        {
                            _instance = new Singleton();
                        }
                    }
                }
                return _instance;
            }
        }
    }

版本四:饿汉式(推荐)

线程安全 延迟加载 加锁
创建对象时未加锁,获取对象时未加锁
public sealed class Singleton
    {
        private static Singleton instance = new Singleton();

        static Singleton()
        {

        }

        private Singleton()
        {

        }

        public static Singleton Instance
        {
            get
            {
                return instance;
            }
        }
    }

版本五:躺平式-静态内部类(推荐)

线程安全 延迟加载 加锁
创建对象时未加锁,获取对象时未加锁
public sealed class Singleton
    {
        private Singleton()
        {

        }
        public static Singleton instance
        {
            get
            {
                return Nested.instance;
            }
        }

        private class Nested
        {
            static Nested()
            {

            }
            internal static readonly  Singleton instance = new Singleton();
        }
    }

版本六:.NET4 的 Lazy<T> 类型(强烈推荐)

线程安全 延迟加载 加锁
创建对象时未加锁,获取对象时未加锁
public sealed class Singleton
    {
       private static readonly Lazy<Singleton> Lazy = new(() => new Singleton());

       public static Singleton Instance => Lazy.Value;

       private Singleton()
       {

       }
    }

参考资料