多线程共享局部变量

Multi Threading Shared Local Variables

我试图完全理解创建调用 class 实例的相同方法的单独线程如何影响方法中的局部变量。

例如我有一个class只有一个方法(除法)

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();
    }

}

有时这段代码运行正常。但有时它会在行上抛出一个除零错误:

int 结果 = Num1 / Num2;

我的假设是其中一个线程在另一个线程调用 Num1 / Num2 之前将 Num1 和 Num2 重置为零。因此导致被零除异常。

这是有道理的,我应该使用锁,但我不明白这些局部变量 Num1 和 Num2 如何在线程之间共享,因为我的理解是局部变量不在线程之间共享?

局部变量不在线程之间共享是对的(通常,每次调用方法时,都会在执行线程的堆栈上分配新的局部变量集,因此每个方法调用的局部变量是完全独立的并且修改其中一个对其他没有影响)。

但不幸的是Num1Num2不是局部变量,而是fields。 class 的同一实例的字段在线程之间共享。

您需要像这样声明它们以使其成为局部变量:

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 class 实例,因此每个线程将使用 Num1Num2 不同实例的字段 Maths class:

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();
}