2011-01-21 1 views
1

スレッドが現在所有していないロックオブジェクトでMonitor.Wait(lockObj)を呼び出すと、SyncronizationLockExceptionがスローされます。Monitor.Wait()を呼び出す前にモニタを取得する必要がある理由

私はこの点を理解していませんか?スレッドがロックを所有していて、したがってMonitor.Wait()を正常に呼び出すことができれば、それはただちにロックをただちに解放します。スレッドが現在所有していないロックを待つことができないのはなぜですか?


更新

私は私の質問に、もう少し説明を加えることにしました。

私が理解したところから、Waitは現在のスレッドをモニタの待機キューに置き、ロックを解除します。その後、パルスまたはパルスは、待ち行列の1つまたはすべてのスレッドを準備完了キューに移動します。モニターが解放されるたびに、レディー・キューの次のスレッド(存在する場合)にロックが与えられます。

なぜ、待機は単に待ち行列にスレッドを追加できませんか?なぜこれを行うにはロックを取得する必要がありますか?これに物理的な理由があるのでしょうか、またはマイクロソフトがクラスを設計して正しい方法で使用するように強制しましたか?

私はそれについて考えて、モニターの待ち行列に何かを置いたり、準備が整ったキューに何かを移動させるのが実際にモニターを操作していると思います。これを行うには自身のモニターが必要になると考えられます。それはそれについて正しい考え方ですか?

私の脳のマルチスレッドは大変です!

答えて

1

Monitor.Waitのポイントは、他のスレッドにロックをかけることです。

最初にロックを所有していない場合は、ポイントはありません。他のスレッドはすでにロックを取得できます。
(いくつかの他のスレッドが既にロックを所有している場合を除き、台無しにそのスレッドを希望Waitを呼び出した場合)

0

ロックせずにMonitor.Waitを呼び出すと、ほとんどの場合、非決定的なバグを紹介します。ロックを取得した直後にMonitor.Waitを呼び出し、ロックを取得してMonitor.Waitを呼び出す間に共有変数を設定しない場合も同じです。

特に、ロックを所有していない場合は、Monitor.Waitを入力する前に、Monitor.Pulseが実行されていないことを確認できません。オペレーティングシステムがMonitor.Wait呼び出しの直前にスレッドAを中断し、何らかの計算を実行した後にMonitor.Pulseを実行しているスレッドBを再開した状況を考えてみましょう。すべての共有変数は、スレッドBがAが待機していることを確信しますが、これはまだ真ではありません。そしてスレッドAはこの時点でMonitor.Waitの実行を停止できません。

また、セマフォーhttp://en.wikipedia.org/wiki/Semaphore_(programmingのアイデアに興味があるかもしれません。あなたはそれらを取得する考えがなくても、彼らを待って、信号を送ることができます。彼らは彼らの状態を保持しているからです。したがって、最初に信号を送ると待つことはできません。

1

Monitor.Waitは、ロックを解除してからを原子的にに再取得するために使用されます。 BCLの他の同期メカニズムではその名声を主張していません。明らかに、Waitは、ロックがまだ存在しない場合は再獲得できません。そのため、例外がスローされます。

Waitが既存のロックを再取得するという事実は、非常に強力なメカニズムです。ビヘイビアのこの基本的な一意性により、BCL内の他のすべての同期メカニズムを構築することができます。

関連する問題