(无效方式)避免C#中的双重检查锁

Cas*_*sen 3 c# multithreading locking

这是避免双重检查锁的有效且优化的方法:

public class SomeBaseClass
{
     protected static object InitializeLock = new object();
     protected static bool IsInitialized = false;

     public void SomeFunction()
     {
         if (!IsInitialized)
         {
             System.Threading.Thread.MemoryBarrier();
             lock (InitializeLock)
             {
                 // do init stuff
                 IsInitialized = true;
             }
     }

     //Do stuff that have to happen when function is called
    }
}
Run Code Online (Sandbox Code Playgroud)

这是双重检查的选择:

public class SomeBaseClass
{
     protected static object InitializeLock = new object();
     protected static bool IsInitialized = false;

     public void SomeFunction()
     {
         if (!IsInitialized)
         {
             lock (InitializeLock)
             {
                 if (!IsInitialized)
                 {                              
                     // do init stuff
                     IsInitialized = true;
                 }
             }
         }

     //Do stuff that have to happen when function is called
    }
}
Run Code Online (Sandbox Code Playgroud)

And*_*rey 6

不,因为线程切换可以在两个线程通过后立即发生 if (!IsInitialized)

有一篇很棒的文章,在创建单例的背景下解释了这个主题:http://csharpindepth.com/Articles/General/Singleton.aspx(作者Jon Skeet)


Eri*_*ert 5

这是今天第二次出现这个问题.看到:

C#手动锁定/解锁

对你的问题的简短回答是否定的,这绝对无效.如果针对正在初始化的任何状态的非易失性读取重新排序"IsInitialized"的非易失性读取,则代码路径从不对其进行任何类型的内存屏障,因此可以重新排序读取,因此"IsInitialized"可以是真实的,而过时的缓存未初始化状态仍然是好的.

你要做的是(1)不要进行双重检查锁定; 这是危险的,或者(2)确保始终存在至少一个IsInitialized的易失性读取,以防止读取初始化状态及时向后移动.