C# 静态类的竞赛条件?

C# 静态类的竞赛条件?,c#,multithreading,static,C#,Multithreading,Static,假设我有一个带有静态方法的静态类 多个线程可以同时调用此静态方法 在这些情况下是否存在潜在的竞争条件: 首先,方法只是驻留在某个地址的一段代码。调用方法的每个线程都将在其自己的私有堆栈上拥有该方法及其局部变量的副本。因此,在案例a中,如果没有其他捕获,它应该是线程安全的 案例b取决于许多因素: 你真的在访问那些成员变量吗 如何访问它们:仅读、读+写等 什么样的成员变量:数据结构、单个值 你有任何同步吗 等等 一般来说,假设您确实访问了类成员,它不应被视为线程安全的A-否。只有当静态方法试图访

假设我有一个带有静态方法的静态类

多个线程可以同时调用此静态方法

在这些情况下是否存在潜在的竞争条件:


首先,方法只是驻留在某个地址的一段代码。调用方法的每个线程都将在其自己的私有堆栈上拥有该方法及其局部变量的副本。因此,在案例a中,如果没有其他捕获,它应该是线程安全的

案例b取决于许多因素:

  • 你真的在访问那些成员变量吗
  • 如何访问它们:仅读、读+写等
  • 什么样的成员变量:数据结构、单个值
  • 你有任何同步吗
  • 等等

一般来说,假设您确实访问了类成员,它不应被视为线程安全的

A-否。只有当静态方法试图访问共享资源时,才会出现争用条件。局部变量对于调用该方法的每个线程都是唯一的

B-是的。这些静态成员将由调用该方法的所有线程共享

假设我有一个带有静态方法的静态类。多个线程可以同时调用此静态方法

在这些情况下是否存在潜在的竞争条件: a-如果该方法仅依赖于局部变量

是的,有潜在的比赛条件

b-如果方法依赖于局部变量和成员字段

是的,有潜在的比赛条件

(a)和(b)的答案是一个更一般的规则的结果,即,每当您从多个线程调用任何方法时,总是有可能出现争用条件。例如,此程序死锁:

class MyClass
{
  static MyClass() 
  {
    // Let's run the initialization on another thread!
    var thread = new System.Threading.Thread(Initialize);
    thread.Start();
    thread.Join();
  }

  static void Initialize() 
  { }

  static void Main() 
  { }
}
它没有字段,有两个完全不做任何事情的方法,还有一个只能在单个线程上访问的局部变量。尽管如此,它还是会立即且持续地陷入僵局。(你知道为什么吗?有关此计划的更多信息,请参阅。)


听起来,如果您的静态方法不访问字段,那么您正在寻找程序线程安全的保证没有这样的保证。您的程序是线程安全的,当且仅当您将其编写为线程安全时

请编辑您的问题以提供一些伪代码或示例以提供更多信息。谢谢。这些都没有任何效果。唯一重要的是多个线程是否使用同一个对象。每个方法调用都有其自己的局部变量副本,因此我99%确定仅使用局部变量不会创建竞争条件。然而,使用成员字段将是有效的。您的“a”和“b”场景的含义并不明显。你能用一些代码来说明你的问题吗?让我们在:
Initialize
是非静态的并且
线程(new MyClass().Initialize)
时做任何更改?或者
线程((MethodInvoker)委托{new MyClass().Initialize();})
?我不确定这个例子是否适合OP的问题框架。我的印象是,他指的是一个由多个外部线程显式调用的静态方法。@BenVoigt:奇怪的是,不是。运行时会检查初始化方法时是否运行静态ctor,而不管它是静态方法还是实例方法。现在您可能会说,除非已经构造了实例,否则不能调用实例初始化方法,在这种情况下,执行构造函数的线程调用了静态构造函数。但是(1)正如我们所看到的,静态构造函数可能还没有完成,(2)如果“this”为空怎么办?在这种情况下,可能没有创建实例。@Tudor:我的观点只是为了说明在多个线程上调用的任何方法都会导致有趣的线程行为。最初的海报是询问当地人、田地等问题,希望能保证他在某些情况下不必认真考虑线程安全。没有这种情况。您必须一直认真思考。@Eric:如果第二个线程(再次)触发静态ctor的调用,我的直觉是,ctor的执行将发生在第二个线程上,这将导致递归线程的创建。您所说的似乎是静态CTOR只在主线程上运行,但该线程当前处于等待状态。这里似乎有一种魔力,一个线程的执行会触发另一个线程上的代码执行(第二个线程导致ctor再次在主线程上执行)。局部变量是唯一的,但是它所引用的对象呢?这可能是共享的。@svick我假设通过“局部变量”,OP并不意味着传递给方法或全局变量的任何内容。换句话说,局部变量是将在方法中创建和消亡的对象。
class MyClass
{
  static MyClass() 
  {
    // Let's run the initialization on another thread!
    var thread = new System.Threading.Thread(Initialize);
    thread.Start();
    thread.Join();
  }

  static void Initialize() 
  { }

  static void Main() 
  { }
}