7 c# singleton multithreading constructor
可能重复:
C#静态构造函数线程是否安全?
Jon Skeet在http://csharpindepth.com/Articles/General/Singleton.aspx上的精彩文章以及我读过的其他文章清楚地表明,双重检查锁定在C#和Java中都不起作用,除非有明确标记实例为"易变".如果不这样做,则将其与null进行比较的检查可能会返回false,即使实例构造函数尚未完成运行.在Skeet先生的第三个样本中,他清楚地说明了这一点:"Java内存模型不能确保构造函数在将新对象的引用分配给实例之前完成.Java内存模型经历了1.5版的重新修改,但是在没有volatile变量的情况下,-check锁定仍然被破坏(如在C#中)
但是,大多数人都同意(包括Skeet先生,他的文章中的第4和第5个样本),使用静态初始化是获取线程安全单例实例的简单方法.他声称"C#中的静态构造函数被指定仅在创建类的实例或引用静态成员时执行,并且每个AppDomain只执行一次."
这是有道理的,但似乎缺少的是保证仅在构造函数完成后才分配对新对象的引用 - 否则我们会遇到使得双重检查锁定失败的同类问题,除非您标记实例像挥发性的.是否有保证,当使用静态初始化来调用实例构造函数(而不是从属性的get {}调用实例构造函数时,就像我们使用双重检查锁定一样),构造函数将在任何其他线程之前完全完成可以获得对象的引用?
谢谢!
在任何其他线程可以获得对象的引用之前,构造函数是否会完全完成?
静态初始化程序将仅(通过系统,至少)每次调用一次AppDomain
,并以同步方式调用"beforefieldinit".因此,假设您没有做任何奇怪的事情,静态初始化程序中分配的任何静态字段应该没问题; 任何其他使用静态字段的尝试都应该在静态构造函数后面保持(阻塞).
只有在构造函数完成后才会分配对新对象的引用
它会在它发生时发生.例如,任何静态字段初始化器都会在您通常认为是构造函数之前发生.但由于其他线程被阻止,这应该不是问题.
然而: