2017-11-27 11 views
3

albahari atricleからマルチスレッドを学習しています。 以下のサンプルでロック_lockerが必要ですか? _messageEventWaitHandleによって保護されているので、私はいいえと思います。私は正しい?EventWaitHandleを持っている場合はロックが必要です

class TwoWaySignaling 
{ 
    static EventWaitHandle _ready = new AutoResetEvent (false); 
    static EventWaitHandle _go = new AutoResetEvent (false); 
    static readonly object _locker = new object(); 
    static string _message; 

    static void Main() 
    { 
    new Thread (Work).Start(); 

    _ready.WaitOne();     // First wait until worker is ready 
    lock (_locker) _message = "ooo"; 
    _go.Set();       // Tell worker to go 

    _ready.WaitOne(); 
    lock (_locker) _message = "ahhh"; // Give the worker another message 
    _go.Set(); 
    _ready.WaitOne(); 
    lock (_locker) _message = null; // Signal the worker to exit 
    _go.Set(); 
    } 

    static void Work() 
    { 
    while (true) 
    { 
     _ready.Set();       // Indicate that we're ready 
     _go.WaitOne();       // Wait to be kicked off... 
     lock (_locker) 
     { 
     if (_message == null) return;  // Gracefully exit 
     Console.WriteLine (_message); 
     } 
    } 
    } 
} 
+2

この例では、 'lock'を削除すると実行の順序が変わることはありません。 – Rotem

+3

ロックを必要とせず、2つのAutoResetEvent間のピンポングにより同期が提供され、同時にスレッドが変数にアクセスできないようにします。 WaitOne()呼び出しはメモリバリアを提供し、変数の更新が別のスレッドから見えるようにします。これらの偶発的な障壁は、あまりにも綺麗ではありませんが、まれではありません。 Barrierクラスの使用を強くお勧めします。そのSignalAndWait()メソッドを使用すると、このコードを理解しやすくなります。そしてもっと効率的です。理解できるコードはスレッドのバグを回避し、効率的なコードは皆を幸せにします。 –

答えて

3

あなたは正しいです。

これらの種類の問題は、試行錯誤で簡単にテストすることはできません。彼らは論理的思考で最もよく分析されます:

  • どのスレッドがどのコードを実行していますか?
  • 他のスレッドで何が起こる可能性があります今すぐ
  • 他のスレッドでCPU時間が増えるとどうなりますか?

メインスレッドはMain()でコードを実行し、ワーカースレッドはコードWork()のみを実行します。それで十分簡単です。

あなたは重要なリソースにアクセスする方法あなたはMain()_messageへのアクセスに注意します見ればWork()_messageへのアクセスが間に常にあるのに対し

_ready.WaitOne(); 

_go.Set(); 

の間で常にあります

_go.WaitOne(); 

_ready.Set(); 

したがって、スレッドの一つは、常に_messageにアクセスする前に、他のを待つことになるとロックが必要とされていません。

0

スレッドが同時に変数_messageにアクセスするのを停止しました。ここでのあなたのロジックは、必ずしも十分ではなく、予測可能な自己完結型のものです。時々あなたは他の場所から読むでしょう、そして、流れは完全に制御可能ではありません。その場合、重要な変数をロックする必要があります。

関連する問題