C#中的单例线程安全 - 为什么要添加双重检查?

Yan*_*hof 4 c# singleton design-patterns locking thread-safety

using System;

public sealed class Singleton
{
   private static volatile Singleton instance;
   private static object syncRoot = new Object();

   private Singleton() {}

   public static Singleton Instance
   {
      get 
      {
         if (instance == null) 
         {
            lock (syncRoot) 
            {
               if (instance == null) 
                  instance = new Singleton();
            }
         }

         return instance;
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

我不明白为什么要仔细检查!我读到这个双重检查是为了解决线程并发问题 - 但是......

  1. 锁将解决它 - 所以我们需要先'如果'

  2. 如果这个单例将没有第一个'if',它仍然是线程安全的 - 对吗?

  3. 如果第一个'if'为false - 那么thread1将初始化'instance'object => now,'instance'不为null且thread1仍然在锁定块中=== >> now,thread2检查第一个' if'并且会得到false =>所以他不会进入'lock'并且迫切地将返回实例并且thread2能够更改'instance'=>的属性,因此thread1 && thread2在同一'实例上'工作' 'object =>所以线程安全在哪里......或者我在这里缺少什么.

gdo*_*ica 6

1.锁将解决它 - 所以我们需要先'如果'

因此,除非您需要创建Singleton的新实例,否则不会锁定thred.
lock是一个非常昂贵的操作,所以值得做额外的检查.

2.如果这个单例将没有第一个'if',它仍然是线程安全的 - 对吗?

是的,但速度要慢得多.

3.Thread1 && thread2在'instance'object =>上'工作',所以线程安全在哪里

这是单例的全部要点,所有线程只有一个实例.那是线程安全的事情......

  • 但是与"if"语句相比,锁是昂贵的,所以留下第一个"if"语句将最终加速你的代码. (3认同)