2017-11-18 197 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