我有一些控制器类的实例属性的代码,如下所示:
public class Controller
{
private static volatile Controller _instance;
private static object syncRoot = new Object();
private Controller() { }
public static Controller Instance
{
get
{
if (_instance == null)
{
lock (syncRoot)
{
if (_instance == null)
_instance = new Controller();
}
}
return _instance;
}
}
public void Start()
{
}
}
Run Code Online (Sandbox Code Playgroud)
通过阅读volatile关键字上的msdn文档后,我不确定第二次空检查是否冗余,以及编写getter的更好方法是这样的:
get
{
lock (syncRoot)
{
if (_instance == null)
_instance = new Controller();
}
return _instance;
}
Run Code Online (Sandbox Code Playgroud)
这两种实现中哪一种更适合多线程性能和DRY'(冗余删除)?
Eri*_*ert 13
这称为"双重检查锁定"模式.这是一种低锁优化的尝试,因此非常危险.
无法保证模式在CLR v1.0上正常运行.是否在后期版本中如此保证是一个有争议的问题; 有些文章说是,有些人说不.这非常令人困惑.
我会完全避免它,除非你有充分的理由认为锁定解决方案不足以满足你的需求.我会使用更高级的原语,Lazy<T>比如Joe Duffy这样的专家.他们更可能是正确的.
这个问题是重复的
有关详细信息,请参阅那里的详细答案.特别是,如果您打算编写任何低锁代码,您必须阅读Vance的文章:
http://msdn.microsoft.com/en-us/magazine/cc163715.aspx
和乔的文章:
http://www.bluebytesoftware.com/blog/PermaLink,guid,543d89ad-8d57-4a51-b7c9-a821e3992bf6.aspx
请注意,Vance的文章声称双重检查锁定可以保证在CLR v2中起作用.我不清楚文章中讨论的保证是否实际上是在CLR v2中实现的; 我从来没有从任何人那里得到一个直接的答案,并且已经听说过它们都是按照规定实施的.再一次,当你自己做这种低锁的东西时,你在没有网的空中飞人; 如果可能的话,避免它.
一个更好的选择是使用Lazy<T>:
private static readonly Lazy<Controller> _instance = new Lazy<Controller>
(() => new Controller());
private Controller() { }
public static Controller Instance
{
get
{
return _instance.Value;
}
}
Run Code Online (Sandbox Code Playgroud)
但是,如果您坚持使用.NET 4之前的版本,我建议您阅读Jon Skeet关于C#中的Singletons的文章.它讨论了上述技术的优点和缺点,以及为.NET 3.5及更早版本提供更好的实例化懒惰实例化单例.