2017-11-18 21 views
2

クラスインスタンスの同じメソッドを呼び出す別々のスレッドを作成すると、メソッド内のローカル変数にどのように影響するかを完全に理解しようとしています。例えばマルチスレッド共有ローカル変数

Iは、単一のメソッドを持つクラスを持っている(分割)

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

2つのスレッドがインスタンス化されるとと呼ばれる分割方法は、以下:

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

} 

時には、このコードは、[OK]を実行します。しかし、それ以外のときには、dividebyzeroエラーが発生します。

int result = Num1/Num2;

私の前提は、スレッドの1つが、他のスレッドがNum1/Num2を呼び出す直前にNum1とNum2をゼロにリセットしていることです。そのため、除算例外が発生します。

これは意味があり、私はロックを使うべきですが、ローカル変数がスレッド間で共有されていなかったので、これらのローカル変数Num1とNum2がスレッド間でどのように共有されているのか分かりません。

+0

ありがとうございました。 – selams

答えて

5

ローカル変数がスレッド間で共有されていないのは当然です(通常、メソッドが呼び出されるたびにローカル変数の新しいセットが実行スレッドのスタックに割り当てられるため、各メソッド呼び出しのローカル変数は完全に分離されます)。そのうちの1つの修正は他のものに影響を与えない)。

しかし、不幸にも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; 
     } 
    } 
} 

また、あなたがスレッドごとMathsクラスの別のインスタンスを作成しcoudので、各スレッドはフィールドNum1と異なるのNum2を使用しますMathsクラスのインスタンス:あなたが同じオブジェクトを使用しているので

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

、1つのタスク内のすべての更新アクションは、他に影響を与えます。

+2

... Num1とNum2はフィールドであり、ローカル変数ではないので、Nufは –

+0

を説明しています。 – Felipe