话不多说直接上代码:
public sealed class Singleton { private static Singleton _instance = null; // Creates an syn object. private static readonly object SynObject = new object(); Singleton() { } public static Singleton Instance { get { // Double-Checked Locking if (null == _instance) { lock (SynObject) { if (null == _instance) { _instance = new Singleton(); } } } return _instance; } } }
很久之前就看到这段代码,一直理解不了为啥要判断两次是否为空.刚刚画着图的时候突然就明白了,见下图:
假如上图还是没看明白的话,可以看下面一段没有两次判空的情况,首先代码如下:
public sealed class Singleton { private static Singleton _instance = null; // Creates an syn object. private static readonly object SynObject = new object(); Singleton() { } public static Singleton Instance { get { if (null == _instance) { lock (SynObject) { _instance = new Singleton(); } } return _instance; } } }
分析见下图:
看完上面先不要着急,先看下面这段代码:
public sealed class Singleton { private static Singleton _instance = null; private static readonly object SynObject = new object(); Singleton() { } /// <summary> /// Gets the instance. /// </summary> public static Singleton Instance { get { lock (SynObject) { return _instance ?? (_instance = new Singleton()); } } } }
看到这里有些同学可能会产生疑问,以上方式的实现方式是线程安全的,如果像上面代码段进行一次判断也是可以实现多线程下单例的,为什么要判断两次呢?
这里我是这样理解的:线程安全的实现方式的问题是要进行同步操作,那么我们可以降低通过操作的次数,所以我们只需在同步操作之前,添加判断该实例是否为null就可以降低通过操作的次数了,这样就是经典的Double-Checked Locking方法了。
时间: 2024-12-20 14:35:16