【问题标题】:Does C# lock object require lazy initializationC#锁对象是否需要延迟初始化
【发布时间】:2016-05-05 22:26:22
【问题描述】:

我可能在某处遗漏了一些非常明显的文档,但静态只读成员变量是否可以保证正确初始化以用作锁定对象?

简而言之,我有一个对外部资源执行操作的库类,该外部资源在任何时候都应该只有一个实例接触它(不必担心另一个进程,它只在一个进程上)。库类本身可以在多个线程中有多个实例,因此为了确保一次只有一个实例访问所述资源,我需要使用锁。

我见过很多这样的锁对象声明。

private static readonly object _lockObj = new object();

这能否保证多个线程不会因为时机不当而同时初始化两个对象并锁定两个对象?或者我应该像这样创建锁定对象。

private static readonly Lazy<object> _lockObj = new Lazy<object>(() => new object());

附:我指的是 C# 的 lock(_lockObj){...} 关键字用于锁定。

【问题讨论】:

  • 可以对任何对象进行锁定。如果你说的是真的,static readonly 字段可能有多个值,这不是预期的。只要他们访问的是同一个类,你就可以开始了。小心泛型类 ;)
  • CLR 保证每个 appdomain 都会初始化一次类型。静态字段初始值设定项在类型的静态构造函数主体之前的类型初始值设定项内运行(如果有的话)。因此,假设两个线程在同一个 appdomain 中激活一个方法,那么就不可能出现它们获得不同锁对象的竞争。
  • 如果它不能像这样工作,那么我看不出你的解决方案会有什么帮助。您只需将问题转移到您有两个 Lazy 实例然后初始化两个不同对象的风险。

标签: c# multithreading lazy-initialization


【解决方案1】:

运行时只保证静态成员字段的一份副本。您甚至可以在没有任何类实例的情况下使用它。用作锁定对象是安全的。

【讨论】:

  • 所以即使对象有点复杂,比如信号量,我也能做到。 public static readonly SemaphoreSlim _semaphore = new SemaphoreSlim(3) 不使用 Lazy 初始化?
  • 是的,_semaphore 是在可以使用之前构造好的。
  • 我认为你不需要一直使用 Lazy。这不像您的应用程序是资源关键型应用程序。
  • @SterlingW 类型的复杂性无关紧要。静态初始化程序保证以串行方式运行 - 在内部它使用全局锁。
猜你喜欢
  • 1970-01-01
  • 2019-07-15
  • 1970-01-01
  • 1970-01-01
  • 2010-10-12
  • 2020-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多