• 设计模式


    class STWindow
    {
        static Window win;
        private STWindow() { }
            
        public static Window GetInstance()
        {
            if (win == null || !win.IsVisible)
            {
                win = new Window();
                win.Height = 200;
                win.Width = 200;
            }
                        
            return win;
        }        
    }
    
    class Singleton
    {
        static Singleton _singleton;
        private Singleton() { }
    
        public static Singleton GetInstance()
        {
            if (_singleton == null)
            {
                _singleton = new Singleton();
            }
            return _singleton;
        }
    }
    

    1. 多线程同时创建实例问题

    多个线程同时访问 Singleton 的 GetInstance() 方法,可能会造成创建多个实例;
    比如 A 先进入后在准备实例化 Singleton 的过程中,B 也进入了,这时 _singleton 还是为 null,然后 B 也去实例化 Singleton 了。

    class Singleton
    {
        static Singleton _singleton;
        private Singleton() { }
    
        public static Singleton GetInstance()
        {
            if (_singleton == null)
            {
                Console.WriteLine("实例化一个 Singleton");
                _singleton = new Singleton();
            }
            Console.WriteLine("返回一个 Singleton");
            return _singleton;
        }
    }
    
    System.Threading.Thread a = new System.Threading.Thread(() =>
    {
        Singleton.GetInstance();
    });
    
    System.Threading.Thread b = new System.Threading.Thread(() =>
    {
        Singleton.GetInstance();
    });
    
    System.Threading.Thread c = new System.Threading.Thread(() =>
    {
        Singleton.GetInstance();
        });
    
    a.Start();
    b.Start();
    c.Start();
    
    实例化一个 Singleton
    实例化一个 Singleton
    返回一个 Singleton
    返回一个 Singleton
    返回一个 Singleton
    

    我们通过加个锁来解决这个问题。

    public static readonly object syncRoot = new object();
    
    public static Singleton GetInstance()
    {
        lock (syncRoot)
        {
            if (_singleton == null)
            {
                Console.WriteLine("实例化一个 Singleton");
                _singleton = new Singleton();
            }
        }
                
        Console.WriteLine("返回一个 Singleton");
        return _singleton;
    }
    
    实例化一个 Singleton
    返回一个 Singleton
    返回一个 Singleton
    线程 0x1a08 已退出,返回值为 0 (0x0)。
    返回一个 Singleton
    线程 0x45b4 已退出,返回值为 0 (0x0)。
    线程 0x5a04 已退出,返回值为 0 (0x0)。
    

    2. 每次实例都要锁的性能问题

    使用双重锁定,只有未实例化时才锁,锁完判断是否还未实例化。

    public static Singleton GetInstance()
    {
        if (_singleton == null)
        {
            lock (syncRoot)
            {
                if (_singleton == null)
                {
                    _singleton = new Singleton();
                }
            }
        }
        return _singleton;
    }
    

    3.饿汉式单例

    class Singleton
    {
        static readonly Singleton _instance = new Singleton();
    
        private Singleton() { }
    
        public static Singleton GetInstance()
        {            
            return _instance;
        }
    }
    

    这种静态初始化的方式是自己被加载时就将自己实例化,因此被称为饿汉式单例;
    而第一次被引用时才将自己实例化的方式被称为懒汉式单例。C# 中饿汉式已足够满足。

  • 相关阅读:
    C语言I博客作业08
    第十一周助教总结
    C语言I博客作业07
    C语言I博客作业06
    C语言I博客作业05
    C语言I作业004
    第十三周助教总结
    C语言I博客作业09
    第十二周助教总结
    C语言I博客作业08
  • 原文地址:https://www.cnblogs.com/MichaelLoveSna/p/14199110.html
Copyright © 2020-2023  润新知