话不多说直接上代码:
public sealed class Singleton
{
private static Singleton _instance = null;
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;
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(){}
public static Singleton Instance
{
get
{
lock (SynObject)
{
return _instance ?? (_instance = new Singleton());
}
}
}
}
看到这里有些同学可能会产生疑问,如果像上面代码进行一次判断也是可以实现多线程下单例的,为什么要判断两次呢?
这里我是这样理解的:线程安全的实现其实就是要进行同步操作,而我们只需在同步操作之前,判断该实例是否为 null 就可以降低通过被 lock 的次数了,这样就是经典的 Double-Checked Locking 了。
评论区