C# 静态方法局部变量与线程安全

C# 静态方法局部变量与线程安全,c#,static,C#,Static,对于普通实例方法,局部变量是线程安全的 如果静态方法中有以下内容: int i = 0; i += 3; 这是线程安全的吗?有陷阱吗 另外,当每个变量都有自己的堆栈时,它到底意味着什么?这是否意味着它自己的堆栈跟踪 谢谢如果您发布的行在方法内部,那么没有理由不使用线程安全。线程没有以任何方式交互-每个线程看到不同的i 如果您试图在线程之间共享i的值,例如通过将i设置为静态字段,则会出现问题。然后就有可能得到一个比赛条件,在这个条件下,你会根据时间得到不同的结果 关于第二个问题,每个线程都有自己

对于普通实例方法,局部变量是线程安全的

如果静态方法中有以下内容:

int i = 0;
i += 3;
这是线程安全的吗?有陷阱吗

另外,当每个变量都有自己的堆栈时,它到底意味着什么?这是否意味着它自己的堆栈跟踪


谢谢

如果您发布的行在方法内部,那么没有理由不使用线程安全。线程没有以任何方式交互-每个线程看到不同的
i

如果您试图在线程之间共享i的值,例如通过将
i
设置为静态字段,则会出现问题。然后就有可能得到一个比赛条件,在这个条件下,你会根据时间得到不同的结果


关于第二个问题,每个线程都有自己的堆栈,而不是每个变量。

下面是一个演示,其中有一个(简单化的)示例来帮助扩展Mark所说的内容:

void Main()
{   
    for (int x = 0; x < 10; x++)
    {
        ThreadPool.QueueUserWorkItem(z=> myClass.DoSomething());
    }

}
public class myClass
{
    public static void DoSomething()
    {
        int i = 0;
        Console.WriteLine (i += 3);
    }
}
void Main()
{   
对于(int x=0;x<10;x++)
{
ThreadPool.QueueUserWorkItem(z=>myClass.DoSomething());
}
}
公共类myClass
{
公共静态无效剂量测定法()
{
int i=0;
Console.WriteLine(i+=3);
}
}
输出: 3. 3. 3. 3. 3. 3. 3. 3. 3. 3.
3

简短回答是“是”,以下方法是线程安全的:

public static int CalcuateSomething( int number ) {
  int i = number * 10;
  return i;
}
所有局部变量都是安全的,只要它们不指向堆上的共享对象

与单线程应用程序一样,此方法的以下调用将返回不同的值

CalculateSomething( 10 ) => 100
CalculateSomething( 20 ) => 200
为什么呢?因为方法编号的每次调用都采用不同的值,因此我也会这样做。函数结束后不会记住i的值,因为i是在堆栈上分配的。在几乎所有语言中,函数都是堆栈上的模型。每次调用不同的方法时,当前方法都会暂停。一个新方法被推送到调用堆栈上并被调用。当该方法完成时,程序解除调用方法的暂停,并在停止的位置(即返回地址)继续。该方法中定义的任何局部变量都是该方法堆栈框架的一部分。我们上述方法的stackframe可以这样考虑:

public Class StackFrameForCalculateSomething implements StackFrame {
  public int ReturnAddress;
  public int i = 0;
  public int number;
}
堆栈可以看作是StackFrame对象的集合

堆栈调用堆栈

每次调用新方法时,程序可能会执行以下操作:

StackFrameForCalculcateSomething s = new StackFrameForCalculateSomething();
s.returnAddress = instructionPointer;
s.number = 10;
callStack.push( s );
s.invoke();

StackFrameForCalculcateSomething s2 = new StackFrameForCalculateSomething();
s2.returnAddress = instructionPointer;
s2.number = 20;
callStack.push( s2 );
s2.invoke();
这对线程意味着什么?在线程的情况下,你会有多个独立的调用堆栈,它们有自己的集合。访问局部变量是安全的,因为线程1的调用堆栈无法访问线程2的调用堆栈,因为它们是独立的对象。就像在单线程情况下一样,s和s2是具有不同数值的不同对象。因此它们彼此独立。考虑S是线程1,S2是线程2。线程1和线程2不共享任何内存,因此它是线程安全的

线程不共享其堆栈帧。它们确实共享堆。

首先,我假设“线程安全”的意思是“当多个线程上发生突变时,某些操作的行为就像原子操作一样”。如果这不是“线程安全”的意思,请在提问之前仔细定义“线程安全”。似乎几乎每个询问堆栈溢出上线程安全问题的人对它的含义都有不同的个人定义

其次,局部变量不是线程安全的。特别是,在lambda或匿名方法的外部变量上闭合的局部变量,或者在迭代器块内的局部变量,在多个线程上进行变异时,不能保证是线程安全的

未在匿名函数的外部变量上闭合且不在迭代器块中的局部变量只能由当前线程进行变异,因此不会同时由多个线程进行变异

另外,当每个变量都有自己的堆栈时,它到底意味着什么


我不知道那是什么意思;变量没有堆栈。线程有堆栈。

请参阅:如果
i
不是一个局部变量,或者如果他在其中有另一个对象执行线程不安全的操作,比如设置没有锁的静态字段或其他操作,那么问题就来了。从逻辑上讲,他的方法也不是线程安全的。但这更像是一个棘手的例外:)评论不错,斯库梅达尔。感谢赛斯的链接,不幸的是,我有时在提交我的帖子后的一段时间内才看到相关链接。