我试图完全理解创建调用类实例的相同方法的单独线程如何影响方法中的局部变量。
例如,我有一个单一方法的课程(Divide)
public class Maths
{
public int Num1;
public int Num2;
public void Divide()
{
for (long i = 0; i < 100000; i++)
{
Num1 = 2;
Num2 = 2;
int result = Num1 / Num2;
Num1 = 0;
Num2 = 0;
}
}
}
实例化两个线程,并按如下方式调用divide方法:
static void Main(string[] args)
{
Maths m = new Maths();
Task t1 = new Task(() => m.Divide());
Task t2 = new Task(() => m.Divide());
List<Task> tl = new List<Task> { t1, t2 };
Parallel.ForEach(tl, task => task.Start());
Console.ReadLine();
}
}
有时这段代码运行正常。但有时候它会抛出一个divbyzero错误:
int result = Num1 / Num2;
我的假设是其中一个线程在另一个线程调用Num1 / Num2之前将Num1和Num2重置为零。因此导致除以零的异常。
这是有意义的,我应该使用锁,但我不明白这些局部变量Num1和Num2是如何在线程之间共享的,因为我的理解是局部变量不在线程之间共享?
答案 0 :(得分:6)
你是正确的,线程之间不共享局部变量(通常,每次调用方法时,它的新局部变量集都在执行线程的堆栈上分配,因此每个方法调用的局部变量是完全独立和修改的其中一个对其他人没有影响。)
但不幸的是Num1
和Num2
不是局部变量,而是fields。类的同一实例的字段在线程之间共享。
您需要像这样对它们进行declate以使它们成为局部变量:
public class Maths
{
public void Divide()
{
int Num1;
int Num2;
for (long i = 0; i < 100000; i++)
{
Num1 = 2;
Num2 = 2;
int result = Num1 / Num2;
Num1 = 0;
Num2 = 0;
}
}
}
或者,您可以为每个线程创建单独的Maths
类实例,因此每个线程将使用Num1
类的不同实例的字段Num2
和Maths
: / p>
static void Main(string[] args)
{
Maths m1 = new Maths();
Maths m2 = new Maths();
Task t1 = new Task(() => m1.Divide());
Task t2 = new Task(() => m2.Divide());
List<Task> tl = new List<Task> { t1, t2 };
Parallel.ForEach(tl, task => task.Start());
Console.ReadLine();
}