在.NET中进行双重检查锁定

eri*_*len 52 .net paradigms multithreading double-checked-locking

我在本文中讨论了为什么在Java中打破了双重检查锁定范例的原因.如果声明变量,范例是否对.NET(特别是C#)有效volatile

Jon*_*eet 75

现在,双重检查锁定在Java和C#中工作(Java内存模型已更改,这是其中一种效果).但是,你必须完全正确.如果你稍微搞砸了,你最终可能会失去线程的安全性.

正如其他答案所述,如果您正在实施单例模式,那么有更好的方法可以实现它.就个人而言,如果我处于需要在双重检查锁定和"每次锁定"代码之间做出选择的情况,我每次都要锁定,直到我得到真正的证据表明它导致了瓶颈.说到线程,一个简单而明显正确的模式是值得的.

  • @IgorK:是的,我相信*当变量标记为volatile时它会起作用. (9认同)
  • @Myster:通过"取出锁"我的意思是"获得锁定".我看到这是不明确的:)是的,删除外部检查. (3认同)
  • @Myster:我个人只是永远拿出锁 - 特别是如果你正在做其他缓慢的事情,这会使锁的成本微不足道. (2认同)

Cam*_*and 25

在C#中实现Singleton模式在第三个版本中讨论了这个问题.

它说:

使实例变量volatile可以使其工作,显式内存屏障调用也是如此,尽管在后一种情况下甚至专家也无法准确地同意需要哪些障碍.我倾向于试图避免专家不同意什么是对的,哪些是错的!

作者似乎暗示双重锁定比其他策略更不可能工作,因此不应该使用.


小智 25

.NET 4.0有一种新类型:Lazy<T>它消除了对模式错误的担忧.它是新任务并行库的一部分.

请参阅MSDN并行计算开发中心:http://msdn.microsoft.com/en-us/concurrency/default.aspx

顺便说一句,还有一个补丁包(我认为这是不支持)的.NET 3.5 SP1可以在这里.


Mic*_*rdt 8

注意比在Java中(并且很可能在.Net中),对于单例初始化的双重检查锁定是完全不必要的以及破坏.由于类在第一次使用之前未初始化,因此已经实现了所需的延迟初始化;

private static Singleton instance = new Singleton();
Run Code Online (Sandbox Code Playgroud)

除非您的Singleton类包含在第一次使用Singleton实例之前可以访问的常量之类的东西,否则这就是您需要做的.

  • DCL 从 Java 5 开始就可以工作(请参阅 Jon Skeet 的评论,尽管他没有具体说明您必须做什么才能使其工作)。您需要: 1. Java 5。 2. DCL 引用声明为易失性的(或以某种方式声明为原子的,例如使用 AtomicReference)。 (2认同)