モニターを使用しているときに、すべてのオブジェクトに Ready および Waiting キューがあるのはなぜですか? オブジェクトでスレッドが終了した場合は、次のアイテムを待機キューにポップします。Ready キューは冗長なようです。
コンテキストは .NET、より具体的にはモニター クラスです。
モニターを使用しているときに、すべてのオブジェクトに Ready および Waiting キューがあるのはなぜですか? オブジェクトでスレッドが終了した場合は、次のアイテムを待機キューにポップします。Ready キューは冗長なようです。
コンテキストは .NET、より具体的にはモニター クラスです。
プロデューサー/コンシューマー キューは、Monitor クラスについて学習するための非常に優れたユース ケースです。
キューに作業が散発的に追加されるとします。処理が必要なアイテムが多数ある場合や、キューにアイテムがない状態で長時間が経過する場合があります。
たとえば、キュー内のアイテムを処理するために待機しているコンシューマー スレッドが k 個あるとします。つまり、各スレッドはタイトなループを実装し、常に試行します。
lock
ます (これにより、モニターの「準備完了」キューに入れられます)。オプション "a" を選択すると、k 個のスレッドが準備完了キューを何度も移動して CPU サイクルを浪費し、実行する作業が見つからず、キューの後ろから最初からやり直すことになります。
オプション「b」を選択した場合、「今ここですることは何もないので、寝かせて、何かすることがあるときに起こしてください」と言っていることになります。
オプション "b" を使用すると、キューが空の場合、すぐにすべてのコンシューマーが "待機中" キューで眠っていることがわかり、CPU 時間が無駄になることはありません。
次に、プロデューサーがアイテムをキューに追加すると、Monitor.Pulse が呼び出されます。これにより、「待機中」キューの最初のスレッドが起動され、「準備完了」キューの後ろに移動します (「準備完了」キューが空の場合は、キューの前にもなります)。
スレッドがロックを取得し、キューからこの項目を消費すると、Monitor.Enter が再度呼び出され、「準備完了」キューの後ろに移動します。
.NET でのプロデューサー/コンシューマー キューの従来の実装については、この記事を参照してください。
私があなたの質問を正しく理解していると仮定すると、この 2 つは異なる目的を果たします。
「準備完了」キューは、ロックを取得するとすぐに実行できる状態になっているスレッド用です。彼らはロックを取得するのを待っているだけです。これは主に相互排除のために使用され、2 つのスレッドが同時に同じリソースを使用することを防ぎます。
「待機」キューは、特定のシグナルを待機しているスレッド用です。つまり、モニターがパルスされています。これは調整によく使用されます。たとえば、プロデューサー/コンシューマー キューでは、キューが空の場合、コンシューマーはモニターがパルスされるまで待機してからキューを再度チェックします。誰も生成も消費もしませんが、モニターを所有するスレッドはありません - 使用中のリソースはありません。しかし、モニターは消費者と生産者を調整するために使用されます。