2017-11-18 204 views
2

我想充分了解如何创建单独线程调用一个类实例的同样的方法可以在该方法实现的局部变量。多线程共享本地变量

例如我有一个单一的方法(划分)的一类

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

两个线程被实例化并称为划分方法如下:

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错误:

INT结果= NUM​​1/NUM2;

我的假设是,一个线程被重置NUM1和NUM2零其他线程调用NUM1/NUM2之前。因此造成零除异常。

这将使意义,我应该用一个锁,但我不明白如何将这些局部变量NUM1和NUM2是在线程之间共享,因为我的理解是,局部变量不是线程之间共享?

+0

谢谢,现在有道理。 – selams

回答

5

你是正确的,局部变量不是线程(通常,每次方法被调用时,新的一组之间共享它的局部变量执行线程的堆栈中分配的,每个方法调用,这样局部变量是完全独立的,并其中一个的修改对其他的没有影响)。

但是不幸的是Num1Num2不是局部变量,而是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; 
     } 
    } 
} 

或者,你coud为每个线程创建Maths类的单独的实例,所以每个线程将使用领域Num1和不同Num2Maths类的实例:

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

完美的答案和很好的解释! –

3

由于您使用的是同一个对象,都在同一个任务的更新动作影响其他。

+2

......但只因为NUM1和NUM2的领域,而不是本地变量,如NUF解释 –

+0

是,NUF答案更好地解释它。 – Felipe