我在本文中讨论了为什么在Java中打破了双重检查锁定范例的原因.如果声明变量,范例是否对.NET(特别是C#)有效volatile
?
现在,双重检查锁定在Java和C#中工作(Java内存模型已更改,这是其中一种效果).但是,你必须完全正确.如果你稍微搞砸了,你最终可能会失去线程的安全性.
正如其他答案所述,如果您正在实施单例模式,那么有更好的方法可以实现它.就个人而言,如果我处于需要在双重检查锁定和"每次锁定"代码之间做出选择的情况,我每次都要锁定,直到我得到真正的证据表明它导致了瓶颈.说到线程,一个简单而明显正确的模式是值得的.
在C#中实现Singleton模式在第三个版本中讨论了这个问题.
它说:
使实例变量volatile可以使其工作,显式内存屏障调用也是如此,尽管在后一种情况下甚至专家也无法准确地同意需要哪些障碍.我倾向于试图避免专家不同意什么是对的,哪些是错的!
作者似乎暗示双重锁定比其他策略更不可能工作,因此不应该使用.
.NET 4.0有一种新类型:Lazy
它消除了对模式错误的担忧.它是新任务并行库的一部分.
请参阅MSDN并行计算开发中心:http://msdn.microsoft.com/en-us/concurrency/default.aspx
顺便说一句,还有一个补丁包(我认为这是不支持)的.NET 3.5 SP1可以在这里.
注意比在Java中(并且很可能在.Net中),对于单例初始化的双重检查锁定是完全不必要的以及破坏.由于类在第一次使用之前未初始化,因此已经实现了所需的延迟初始化;
private static Singleton instance = new Singleton();
除非您的Singleton类包含在第一次使用Singleton实例之前可以访问的常量之类的东西,否则这就是您需要做的.