ネタバレ注意:質問は最後のフレーズです。
C#では、条件変数を使用する従来のパターンは次のようになります。
lock (answersQueue)
{
answersQueue.Enqueue(c);
Monitor.Pulse(answersQueue); // condition variable "notify one".
}
およびその他のスレッド:
lock (answersQueue)
{
while (answersQueue.Count == 0)
{
// unlock answer queue and sleeps here until notified.
Monitor.Wait(answersQueue);
}
...
}
これは私のコードから抜粋した例です。パルスをロックスコープの外に置くと、コンパイルされません。ただし、これは正しい方法です。cf:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686903(v=vs.85).aspx および: http: //www.installsetupconfig.com/win32programming/threadprocesssynchronizationapis11_7.html ( "中身")
そして確かに、あなたがまだクリティカルセクションにいるときに眠っているスレッドに合図するのはばかげています。スリーピングスレッドは(すぐにではなく)ウェイクアップできないため、批判的なセクションの内側にもあるためです!
したがって、.NETまたはC#のPulse呼び出しが実際にはロックオブジェクトにフラグを立てているだけで、スコープ外になると、この時点で条件変数を実際に「パルス」することを願っています。そうしないと、最適性の問題が発生するためです。
では、なぜMonitorオブジェクトのデザインがそのように選択されたのでしょうか。
編集:
私はこの論文で答えを見つけました: http ://research.microsoft.com/pubs/64242/implementingcvs.pdf セクション「信号とブロードキャストの最適化」とNTカーネルに関する前のセクションとセマフォの上に条件変数を作成する方法、これが「ダーンドキュー」を導入する理由です。今ではそれが私をより良いエンジニアにします。