代码之家  ›  专栏  ›  技术社区  ›  selams

多线程共享局部变量

  •  4
  • selams  · 技术社区  · 7 年前

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

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

    有时此代码运行正常。但其他时候,它会在线路上抛出一个dividebyzero错误:

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

    1 回复  |  直到 7 年前
        1
  •  7
  •   Ňuf    7 年前

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

    但不幸的是 Num1 Num2 不是局部变量,但 fields . 类的同一实例的字段在线程之间共享。

    您需要这样对其进行解密,使其成为局部变量:

    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 的不同实例 数学 类别:

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