「C# 3.0 の概要」のスレッドに関するテキストの説明
-
22-09-2019 - |
質問
読んでいる間 C# 3.0 の概要 による ジョセフとベン・アルバハリ, 、次の段落を見つけました(673ページ、「」というタイトルのセクションの最初の段落)ウェイトとパルスによるシグナリング")
「 モニター クラスは 2 つの静的メソッドを介して別のシグナリング構造を提供します。 待って そして 脈. 。原則として、カスタム フラグとフィールド ( ロック ステートメント)、次に紹介します 待って そして 脈 CPU の回転を軽減するコマンド。この低レベルのアプローチの利点は、 待って, 脈, 、 そしてその ロック ステートメントを使用すると、次の機能を実現できます。 自動リセットイベント, 手動リセットイベント, 、 そして セマフォ, 、 同様に 待機ハンドルの静的メソッド 全部待つ そして 待ってください. 。さらに、 待って そして 脈すべての待機ハンドルが普通に挑戦されている状況では居住する可能性があります。」
私の質問は、の正しい解釈は何ですかということです。 最後 文?
- WaitOne() が特定の待機ハンドルでたまにしか呼び出されない、まともな/大量の待機ハンドルがある状況。
- 適切な/多数の待機ハンドルがある状況では、複数のスレッドが特定の待機ハンドルでブロックされる傾向がほとんどありません。
- 別の解釈も。
また、そのような状況のわかりやすい例と、おそらく他の方法ではなく待機とパルスを使用した方が効率的に処理される方法および/または理由を教えていただければ幸いです。
ありがとう!
編集:ネットでテキストを見つけました ここ
解決
これが何を言っているのかというと、状況によっては、Wait と Pulse の方が待機ハンドルよりも単純な解決策を提供するということです。一般に、これは次の場合に発生します。
- 通知者ではなくウェイターがブロックを解除するタイミングを決定します
- ブロック条件には単純なフラグ以上のもの (おそらく複数の変数) が含まれます。
このような状況でも待機ハンドルを使用できますが、待機/パルスの方が単純になる傾向があります。Wait/Pulse の優れた点は、Wait が待機中に基礎となるロックを解放することです。たとえば、次の例では、ロックの安全な範囲内で _x と _y を読み取りますが、そのロックは待機中に解放され、別のスレッドがこれらの変数を更新できるようになります。
lock (_locker)
{
while (_x < 10 && _y < 20) Monitor.Wait (_locker);
}
次に、別のスレッドが (ロックによって) _x と _y をアトミックに更新し、パルスを送信してウェイターに信号を送ります。
lock (_locker)
{
_x = 20;
_y = 30;
Monitor.Pulse (_locker);
}
Wait/Pulse の欠点は、間違えて間違いを犯しやすいことです (たとえば、変数を更新して Pulse するのを忘れるなど)。待機ハンドルを備えたプログラムが待機/パルスを備えたプログラムと同様に単純な状況では、その理由から待機ハンドルを使用することをお勧めします。
効率/リソース消費 (あなたがほのめかしていたと思います) の観点から見ると、通常、Wait/Pulse の方が高速で軽量です (マネージド実装を備えているため)。ただし、これが実際には大した問題になることはほとんどありません。その点で、Framework 4.0 には、ManualResetEvent と Semaphore の低オーバーヘッド マネージド バージョン (ManualResetEventSlim と SemaphoreSlim) が含まれています。
Framework 4.0 には、Wait/Pulse の必要性を軽減するさらに多くの同期オプションも提供されています。
- カウントダウンイベント
- バリア
- PLINQ / データ並列処理 (AsParallel、Parallel.Invoke、Parallel.For、Parallel.ForEach)
- タスクと継続
これらはすべて Wait/Pulse よりもはるかに高レベルであり、IMO は信頼性が高く保守可能なコードを作成するのに適しています (当面のタスクを解決できると仮定して)。