【问题标题】:Race condition in c# static constructorc#静态构造函数中的竞争条件
【发布时间】:2012-04-23 05:12:45
【问题描述】:

我正在和一个朋友辩论,他说静态构造函数可以让位于竞争条件,因为静态构造函数可以被多次调用。似乎这只能在大容量多线程环境中发生。这甚至可能吗?

我找不到任何文件来证明他错了。有人对此有任何见解吗?

谢谢!

【问题讨论】:

  • 如果一个新线程做了一些会触发静态构造函数的事情,而静态构造函数已经在另一个线程上运行,就会出现竞争条件。线程将阻塞,直到静态构造函数完成运行。但是静态构造函数可能正在等待该新线程完成。见stackoverflow.com/a/8883117/385844

标签: c# race-condition static-constructor


【解决方案1】:

这可能吗?

没有。 CLR 会为您处理此问题,并防止多次调用静态构造函数。

这在 C# 语言规范中多次说明。例如,第 3.1 节规定:

每个应用程序域最多运行一次类型的静态构造函数。

【讨论】:

  • 这是不正确的。埃里克在这里举了一个例子:stackoverflow.com/a/9792537/351385
  • @Tergiver 我正在处理 OP 的声明“可以让位于竞争条件,因为可以多次调用静态构造函数”-始终可以在任何代码中创建自己的竞争条件,在任何地方。没有线程安全保证,但规范确实提供了静态构造函数只会被调用一次的保证,因此特定的竞争条件可能不存在。
  • 但问题是,“是否有可能多次调用 cctor?”答案是,“是的,它可能的。”仅当您从 cctor 本身内部发起呼叫时才有可能,但实际上是可能的。
  • @Tergiver:我认为你们两个正在互相交谈。在 C# 程序中,两个线程的竞争是否可能导致其中一个线程先于另一个运行 cctor?是的。那场比赛有可能导致僵局吗?是的。是否有可能两个线程竞争,让它们同时在 cctor 中结束,然后在 cctor 内的代码中存在竞争?不;锁可以防止这种情况发生。
【解决方案2】:

每个 AppDomain 仅调用一次静态构造函数。
ECMA-335 声明 CLI 应保证:

"对于任何给定的类型,类型初始化器应该只执行一次, 除非用户代码显式调用。”

我还没有听说过在 C# 中调用类型初始化器的便捷方法。

只有在类型初始值设定项之间创建循环依赖时,才会遇到问题。
有关该问题的有趣文章请参见此处:
https://msmvps.com/blogs/jon_skeet/archive/2012/04/07/type-initializer-circular-dependencies.aspx)

【讨论】:

  • 完美!感谢您的帮助。
  • 你应该知道, List 和 List 是两种不同的类型。因此,例如 List 的静态构造函数将被调用两次。
  • @AenSidhe 因为它们是不同的类型,所以不是同一个静态构造函数。将类型参数(如 int 或 string)应用于 List 后,将创建一个封闭类型。不同的类型也都有自己的一组静态变量。不会调用开放类型 List 的静态构造函数。有关详细信息,请参阅C# specification 的第 4.4.2 节。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-09
  • 1970-01-01
  • 1970-01-01
  • 2017-07-13
  • 2013-02-27
  • 2011-05-06
相关资源
最近更新 更多