albahari atricleからマルチスレッドを学習しています。 以下のサンプルでロック_locker
が必要ですか? _message
はEventWaitHandle
によって保護されているので、私はいいえと思います。私は正しい?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);
}
}
}
}
この例では、 'lock'を削除すると実行の順序が変わることはありません。 – Rotem
ロックを必要とせず、2つのAutoResetEvent間のピンポングにより同期が提供され、同時にスレッドが変数にアクセスできないようにします。 WaitOne()呼び出しはメモリバリアを提供し、変数の更新が別のスレッドから見えるようにします。これらの偶発的な障壁は、あまりにも綺麗ではありませんが、まれではありません。 Barrierクラスの使用を強くお勧めします。そのSignalAndWait()メソッドを使用すると、このコードを理解しやすくなります。そしてもっと効率的です。理解できるコードはスレッドのバグを回避し、効率的なコードは皆を幸せにします。 –