wangliuwei

导航

 

1.什么是单例模式

  保证一个类最多只有一个实例(实例化控制),并且提供一个访问它的全局访问点(全局访问)。

2.什么时候用

  当创建一个对象比较耗费资源,而这个对象的实例只要有一个就可以使用,这个时候可以用到单例模式。

  单例模式解决了,如何实现一个类只能被创建一次的问题。

3.代码示例

using System;

namespace mydotnet
{
    class Program
    {
        static void Main(string[] args)
        {
            Singleton singleton =  Singleton.GetInstance();//客户端获取实例
        }
    }  

    public sealed class Singleton
    {
        private Singleton(){}//私有化构造函数,防止外部实例化内部可以使用

        private static Singleton instance;//必须是静态的,静态方法才能调用

        public static Singleton GetInstance(){//公用静态方法,外部可以调用
            if(instance == null)
            {
                instance = new Singleton();
            }
            return instance;
        }      

    }
}

4.并发问题解决

上述代码是懒汉模式,第一次使用才会创建。发生并发时,可能会多次创建,解决并发可以考虑加lock。代码如下:

using System;

namespace mydotnet
{
    class Program
    {
        static void Main(string[] args)
        {
            Singleton singleton =  Singleton.GetInstance();//客户端获取实例
        }
    }  

    public sealed class Singleton
    {
        private Singleton(){}//私有化构造函数,防止外部实例化,内部可以使用

        private static Singleton instance;//必须是静态的,静态方法才能调用

        private static readonly object syncLock = new object();//不直接锁定 instance是因为instance不一定已经创建了,lock的内容需要非空的引用类型

        public static Singleton GetInstance(){//公用静态方法,外部可以调用
            lock(syncLock)
            {
                if(instance == null)
                {
                    instance = new Singleton();
                }
                return instance;
            }
        }      

    }
}

  

lock的作用是锁定某一代码块,让同一时间只有一个线程访问该代码块,详细参考:https://www.cnblogs.com/liuqiyun/p/9118382.html

5.双重锁定

        public static Singleton GetInstance(){//公用静态方法,外部可以调用
            if(instance == null)//避免没必要的lock资源浪费
            {
                lock(instance)
                {
                    if(instance == null)//不能去掉,如果同时进入lock还是可以重复创建
                    {
                        instance = new Singleton();
                    }
                    return instance;
                }
            }
        } 

6.饿汉模式

  程序初始化时,就创建实例,不管用不用到。

       饿汉模式,不要显式编写线程安全代码,就可以解决多线程环境下是否安全的问题。

  解决方式使用静态初始化,代码如下:

using System;

namespace mydotnet
{
    class Program
    {
        static void Main(string[] args)
        {
            Singleton singleton =  Singleton.GetInstance();//客户端获取实例
        }
    }  

    public class Singleton
    {
        private Singleton(){}//私有化构造函数,防止外部实例化,内部可以使用

        private readonly static Singleton instance = new Singleton();//静态初始化,不需要显式的线程安全代码
     //readonly,只能在静态初始化期间或在类的构造函数中修改,不写也没事,防止在其他方法中修改
public static Singleton GetInstance(){ return instance; } } }

也可以不写GetInstance方法,直接把instance设置为public,客户端直接写Singleton.instance实现更简单。

using System;

namespace mydotnet
{
    class Program
    {
        static void Main(string[] args)
        {
            Singleton singleton =  Singleton.instance;//客户端获取实例
        }
    }  

    public class Singleton
    {
        private Singleton(){}//私有化构造函数,防止外部实例化,内部可以使用

        public readonly static Singleton instance = new Singleton();

    }
}

 

posted on 2019-11-06 12:58  wangliuwei  阅读(173)  评论(0编辑  收藏  举报