2017-11-16 19 views
-2

私は、スレッドで遊ぶように設計されたシンプルなクラスを持っています。メンバ変数numは0に初期化され、numは増分してからnumを大きく減らすmodifyというメソッドがあります。プログラムが実行されると、2つのスレッドが作成され、どちらも変更を実行してから、タイマーを開始してスレッドを開始します。 whileループを使用して、両方のスレッドが実行を完了するのを待ってから、タイマーを停止し、経過した時間をコンソールに出力します。クラス:マルチスレッドのパフォーマンスへのロックの影響

public class Threading 
{ 

    public static void Main() 
    { 
     Threading t = new Threading(); 
     t.demo(); 
    } 

    private int num = 0; 

    public void doThreading() 
    { 

     Thread t1 = new Thread(modify); 
     Thread t2 = new Thread(modify); 

     t1.Start(); 
     t2.Start(); 

     Stopwatch timer = new Stopwatch(); 
     timer.Start(); 

     while (thread1.IsAlive || thread2.IsAlive) 
     { 

     } 

     timer.Stop(); 
     Console.WriteLine("Took: " + timer.ElapsedMilliseconds + " milliseconds"); 

     Console.Read(); 
    } 

    public void modify() 
    { 
     for (int i = 0; i < 1000000000; i++) 
     { 
      count++; 
      count--; 
     } 
    } 
} 

プログラムを実行した後、numは競合状態のため0になりません。

public void modify() 
    { 
     for (int i = 0; i < 1000000000; i++) 
     { 
      lock (this) { count++; } 
      lock (this) { count--; } 
     } 
    } 

プログラムを実行した後にnumが0になるように、修正メソッドにロックを追加すると、プログラムの実行に8倍の時間がかかります。なぜそれがずっと長くかかるのか分かりませんが、実行するのに4倍の時間がかかると私は期待しています。なぜそれがずっと長くかかるのか?

+0

Lol、なぜ4ではなく8を期待しますか? :)あなたはなぜ4、5ではなく2ではなく11を選択するのですか?これを期待するのは変です。 – Backs

+0

マルチスレッドとロックについての私の理解は非常に限られています.2スレッドと2つのコードセグメントが別々のロックにあるので、減速は2倍になると思います。ロックにアクセスすることによるオーバーヘッドを考えると、スレッドを強制的にお互いに待つコストがかかるのですが、そのような単純なコードでは、ロックにアクセスする際のオーバーヘッドがかなり重くなる可能性があります –

+0

まあ、間違った質問です。 「どうすればロックするのが驚くほど効率的なのか」 –

答えて

0

lockは(あなたが望むすべてがintをインクリメントロックすることで、すなわちcount++原子を作る)このような場合に非常に高価ように見えることができます。代わりにInterlockedを使用してください:

public void modify() 
{ 
    for (int i = 0; i < 1000000000; i++) 
    { 
     Interlocked.Increment(ref count); 
     Interlocked.Decrement(ref count); 
    } 
}