在普通实例方法中,局部变量是线程安全的。
如果我在静态方法中有以下内容:
int i = 0;
i += 3;
这段代码是线程安全的吗?有什么需要注意的吗?
另外,当每个变量都有自己的堆栈时,这究竟意味着什么?这是否意味着它拥有自己的堆栈跟踪信息?
谢谢
简短的回答是,下面的方法是线程安全的:
public static int CalcuateSomething( int number ) {
int i = number * 10;
return i;
}
只要本地变量不指向堆上的共享对象,它们就是安全的。
正如在单线程应用程序中一样,该方法的以下调用将返回不同的值。
CalculateSomething( 10 ) => 100
CalculateSomething( 20 ) => 200
为什么会这样呢?因为每次调用number方法时,都会取得不同的值,因此i的值也会随之改变。由于i是在堆栈上分配的,所以当函数结束时不会记住i的值。几乎所有语言的函数都是基于堆栈模型的。每次调用不同的方法时,当前方法会暂停,新方法被推入调用堆栈并被调用。当该方法完成时,程序会取消暂停调用方法并从返回地址继续执行(即在returnAddress处)。任何在方法内定义的本地变量都是该方法堆栈帧的一部分。我们上面的方法的堆栈帧可以像这样考虑:
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();
这里有一个(简单的)示例演示,以帮助扩展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);
}
}
i
不是一个局部变量。 - Seth