C#设计模式系列之单例模式

247 阅读3分钟

单例模式

在程序运行期间有些特殊的变量(variable)或类(calss),需要保证它们在程序中只有一个实例,才能使得程序逻辑的正确性,效率。这样的实例称之为==单例==。 单例是由设计者关心的,而不是使用者。


代码实现


单线程单例模式

非线程安全,当thread01在进行 if (_instance == null)判断时,返回true,此时thread01也进行此判断,也返回true,thread01和thread01各自创建一个对象,违背单例模式原则

    /// <summary>
    /// 单线程-单例模式
    /// 非线程安全,当thread01在进行  if (_instance == null) 判断时,返回true,
    /// 此时thread01也进行此判断,也返回true,
    /// thread01和thread01各自创建一个对象,违背单例模式原则
    /// </summary>
    public class SingleThread_SingleTon
    {
        private static SingleThread_SingleTon _instance = null;
        private SingleThread_SingleTon() { }
        public static SingleThread_SingleTon Inst
        {
            get
            {
                if (_instance == null)
                {
                    _instance = new SingleThread_SingleTon();
                }
                return _instance;
            }
        }
    }

多线程单例模式

线程安全,对单线程单例进行加锁,保证只创建一个实例. 注意:==volatile==,此关键字用于修饰变量;在线程内存和主内存(缓存)之间同步某个变量,编译器在优化代码时候,会把常用的代码或变量加入缓存Cache中,下次再用到的时候,就优先读取Cache,这样大大提升效率;下次可能还是从Cache中读取A的值,此时A的值已经不是原来的值了,读取的就是一个脏数据,bug便随之而来。volatile 就是告诉编译器,变量A是可变的,不要加入Cache中。

    /// <summary>
    /// 多线程-单例模式
    /// 线程安全,对单线程单例进行加锁,保证只创建一个实例
    /// 注意:volatile,此关键字用于修饰变量;在线程内存和主内存(缓存)之间同步某个变量
    /// 编译器在优化代码时候,会把常用的代码或变量加入缓存Cache中,下次再用到的时候,就优先读取Cache,这样大大提升效率;
    /// 但是这随之产生一个问题,再多线程程序中,thread01执行后,编译器把变量A放入Cache中,thread01对变量A进行了修改,但是thread01并不知道A已经被修改,
    /// 下次可能还是从Cache中读取A的值,此时A的值已经不是原来的值了,读取的就是一个脏数据,bug便随之而来。
    /// volatile 就是告诉编译器,变量A是可变的,不要加入Cache中。
    /// </summary>
    public class MutilThread_SingleTon
    {
        // 注意此处的 volatile
        private volatile static MutilThread_SingleTon _instance = null;
        private static object _lock = new object();
        private MutilThread_SingleTon() { }
        public static MutilThread_SingleTon Inst
        {
            get
            {
                lock (_lock)
                {
                    if (_instance == null)
                    {
                        _instance = new MutilThread_SingleTon();
                    }
                }
                return _instance;
            }
        }
    }

静态单例模式

在运行期间计算变量的值,且只读,保证在程序运行期间该变量只被初始化一次

    /// <summary>
    /// 静态单例模式
    /// static readonly 在运行期间计算变量的值,且只读,保证在程序运行期间该变量只被初始化一次
    /// </summary>
    public class Static_SingleTon
    {
        private Static_SingleTon() { }
        public static readonly Static_SingleTon Inst = new Static_SingleTon();
    }

本文使用 mdnice 排版