使用C#类只有静态方法而没有变量时会出现并发问题吗?

cha*_*r m 12 c# concurrency multithreading

我是否正确理解所有线程都在自己的堆栈中具有方法变量的副本,因此从不同的线程调用静态方法时不会出现问题?

Jam*_*are 16

是的,不是.如果参数是值类型,那么是的,他们有自己的副本.或者,如果引用类型是不可变的,则它不能被更改,并且您没有问题.但是,如果参数是可变引用类型,那么传入的参数仍然可能需要考虑线程安全问题.

那有意义吗?如果您将引用类型作为参数传递,则它的引用将按"值"传递,因此它是引用回旧对象的新引用.因此,您可能有两个不同的线程可能以非线程安全的方式更改同一对象.

如果每个这些实例的创建和使用使用它们在线程,那么机会是很低,你会得到一点,但我只是想强调的是,仅仅因为你使用静态方法只有当地人/参数是不是一个保证线程安全(当然与Chris所述的实例相同).

  • +1注意到静态的使用(或缺乏静态)并不能保证任何东西——相同的规则也适用于非静态方法。 (2认同)

Eri*_*ert 10

我是否正确理解所有线程都在自己的堆栈中具有方法变量的副本,因此从不同的线程调用静态方法时不会出现问题?

没有.

首先,"所有线程都在自己的堆栈中有方法的局部变量的副本"是错误的.只有当生命周期很短时,才会在堆栈上生成局部变量.如果局部变量是(1)封闭的外部变量,(2)在迭代器块中声明,或(3)在异步方法中声明,则局部变量可能具有任意长的寿命.

在所有这些情况下,通过在一个线程上激活方法而创建的局部变量以后可以由多个线程进行突变.这样做不是线程安全的.

其次,从不同的线程调用静态方法时有很多可能的问题.有时在堆栈上分配局部变量的事实并没有神奇地使静态方法对共享内存的访问突然纠正.

使用C#类只有静态方法而没有变量时会出现并发问题吗?

我假设你的意思是"没有静态变量",而不是"没有局部变量".

绝对可以.例如,这里的程序没有静态变量,没有非静态方法,除了第二个线程之外没有创建任何对象,还有一个局部变量来保存对该线程的引用.除了cctor之外,其他方法都没有实际做任何事情.这个程序陷入僵局. 你不能认为只是因为你的程序很简单,它不包含任何线程错误!

练习给读者:描述为什么这个似乎不含锁的程序实际上是死锁.

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() 
  { /* TODO: Add initialization code */ }

  static void Main() 
  { }
}
Run Code Online (Sandbox Code Playgroud)

听起来你正在寻找一种神奇的方式来了解你的程序没有线程问题.除了使它成为单线程之外,没有这种神奇的方式可以了解它.您将不得不分析您对线程和共享数据结构的使用.

  • 静态ctor保证在任何静态成员(在这种情况下为"Initialize"方法)被允许执行之前完成,但是ctor正忙着等待等待该ctor的线程. (2认同)