线程安全单静态方法初始化
本文关键字:初始化 静态方法 安全 线程 | 更新日期: 2023-09-27 18:31:31
我正在实现一个单例模式,并且需要初始化是线程安全的。
我已经看到了几种方法,例如使用双重检查锁定实现或其他技术(即:http://csharpindepth.com/articles/general/singleton.aspx)
我想知道以下方法(类似于本文中的第四个版本)是否是线程安全的。我基本上是在静态字段初始值设定项中调用一个方法,该方法创建实例。我不在乎懒惰。谢谢!
public static class SharedTracerMock
{
private static Mock<ITracer> tracerMock = CreateTracerMock();
private static Mock<ITracer> CreateTracerMock()
{
tracerMock = new Mock<ITracer>();
return tracerMock;
}
public static Mock<ITracer> TracerMock
{
get
{
return tracerMock;
}
}
}
是的,这是线程安全的 - 尽管它不是正常的单例模式,因为您的类本身没有实例。它更像是一种"单值工厂模式"。该类将只初始化一次(假设没有任何东西调用带有反射的类型初始值设定项),并且在一个线程中初始化时,任何其他请求TracerMock
线程都必须等待。
不过,也可以通过删除该方法来简化代码:
public static class SharedTracerMock
{
private static readonly Mock<ITracer> tracerMock = new Mock<ITracer>();
public static Mock<ITracer> TracerMock { get { return tracerMock; } }
}
请注意,我也将该字段设置为只读,这有助于清晰度。我通常也会像这样将琐碎的 getter 全部粘贴在一行上,以避免大量只带大括号的大量行(一个返回语句的 7 行代码感觉有点矫枉过正)。
在 C# 6 中,可以使用只读自动实现的属性进一步简化此操作:
public static class SharedTracerMock
{
public static Mock<ITracer> TracerMock { get; } = new Mock<ITracer>();
}
当然,仅仅因为此属性是线程安全的并不意味着它返回引用的对象将是线程安全的......不知道Mock<T>
,我们真的看不出来。