如何实现一个单例模式 c#双重锁检查

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何实现一个单例模式 c#双重锁检查相关的知识,希望对你有一定的参考价值。

你好!以下是标准的Singleton pattern with Double-check lock。

    public class SingletonClass
    
        private static readonly object _lock = new object();
        private static volatile SingletonClass _instance;
        public static SingletonClass Instance
        
            get
            
                if (_instance == null)
                
                    lock (_lock)
                    
                        if (_instance == null)
                        
                            _instance = new SingletonClass();
                        
                    
                
                return _instance;
            
        
        private SingletonClass()
        
            //your constructor
        
    

如果你的.NET在4.0以上,可以借助Lazy<T>泛型更优雅的实现单例模式:

    public class LazySingleton
    
        private static readonly Lazy<LazySingleton> _instance = new Lazy<LazySingleton>(() => new LazySingleton());
        private LazySingleton()
        
            //your constructor
        
        public static LazySingleton Instance  get  return _instance.Value;  
    

参考技术A 参考这篇博文【链接】http://blog.csdn.net/sinat_20559947/article/details/48311915 很详细,有样例代码。

单例模式双重检查锁模式为什么必须加 volatile?

单例模式双重检查锁模式为什么必须加 volatile?

学习设计模式时候,知道单例模式是一种很常见的设计模型,其目的就是为了避免创建过多的对象,给jvm造成比较大的压力,之前也对单例模型进行了比较详细的描述,详情参考我之前博客:链接

如果要实现一种线程安全的单例模型,一般都会采用双重检查锁模式


public class Singleton 

    private static volatile Singleton instance;

    public static Singleton getInstance() 
        if (instance == null) 
            synchronized (Singleton.class) 
                if (instance == null) 
                    instance = new Singleton();
                
            
        
        return instance;
    


这里,就会有疑问,为什么要双重检查?

答:这里分情况,如果不用第一个if判断,在多线程情况下,所有的线程都会进行抢锁,所以其实就是串行执行的;如果不用第二个if判断,因为经过第一个if判断,多个线程都会进来,不过只有一个线程能抢到锁,因为singleton对象是null,所以会进行new Singleton,这种情况,如果不加第二个if判断,第一个线程创建对象之后,之后线程会继续创建的,所以这种就没做到单例

双重检查的原因知道之后,为什么要加volatile关键字?在前面的学习,我们知道了volatile关键字有两个关键作用,volatile可以保证并发的可见性,同时也可以保证有序性。所以上面代码Singleton对象加上volatile关键字的作用主要是为了保证有序性。

在new Singleton时候,会进行如下的过程,①先给Singleton分配内存空间、②调用Singleton的构造函数进行初始化操作③将Singleton对象指向分配的内存空间

所以,不加volatile关键字,进行代码编译时候是会进行指令重排序的,如图,new Singleton的过程不一定是按照123这个顺序来的,可能是132顺序执行,这种情况,调用第3步,Singleton对象已经不为null,所以会被其它线程调用,不过还没进行第2步初始化操作,所以会报错

以上是关于如何实现一个单例模式 c#双重锁检查的主要内容,如果未能解决你的问题,请参考以下文章

双重检查锁实现单例模式的线程安全问题

双重检查锁实现单例(java)

单例模式的双重加锁机制为啥要两次检查,第一次检查完不是已经知道了吗?

单例模式双重检查锁模式为什么必须加 volatile?

单例模式双重检查锁模式为什么必须加 volatile?

单例陷阱——双重检查锁中的指令重排问题