7

JosephとBenAlbahariによるC#3.0の概要を読んでいるときに、次の段落に出くわしました(673ページ、「待機とパルスによるシグナリング」というタイトルのセクションの最初の段落)

Monitorクラスは、 WaitPulseの2つの静的メソッドを介して別のシグナリング構造を提供します。原則として、カスタムフラグとフィールド( lockステートメントで囲まれています)を使用してシグナリングロジックを自分で記述し、 WaitコマンドとPulseコマンドを導入してCPUの回転を軽減します。この低レベルのアプローチの利点は、WaitPulse、およびlockステートメントだけで、 AutoResetEventManualResetEventSemaphore、およびWaitHandleの機能を実現できることです。の静的メソッドWaitAllおよびWaitAny。さらに、Wait and Pulse は、すべての待機ハンドルが同じようにチャレンジされる状況で受け入れられる可能性があります。」

私の質問は、最後の文の正しい解釈は何ですか?

  • WaitOne()が特定の待機ハンドルでたまにしか呼び出されない、まともな/多数の待機ハンドルがある状況。
  • 適切な/多数の待機ハンドルがあり、特定の待機ハンドルで複数のスレッドがブロックされることはめったにない状況。
  • 他の解釈。

また、そのような状況の例と、おそらく他の方法ではなく、待機とパルスを介してそれらがより効率的に処理される方法および/または理由を明らかにしていただければ幸いです。

ありがとうございました!

編集:私はここでオンラインでテキストを見つけました

4

1 に答える 1

5

これが言っていることは、WaitandPulseが待機ハンドルよりも簡単な解決策を提供するいくつかの状況があるということです。一般に、これは次の場合に発生します。

  • 通知者ではなくウェイターが、ブロックを解除するタイミングを決定します
  • ブロッキング条件には、単純なフラグ(おそらくいくつかの変数)以上のものが含まれます

このような状況でも待機ハンドルを使用できますが、待機/パルスはより単純になる傾向があります。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は、待機/パルスの必要性を減らす、より多くの同期オプションも提供します。

  • CountdownEvent
  • バリア
  • PLINQ /データ並列処理(AsParallel、Parallel.Invoke、Parallel.For、Parallel.ForEach)
  • タスクと継続

これらはすべて、Wait / Pulseよりもはるかに高レベルであり、IMOは、信頼性が高く保守可能なコードを作成するのに適しています(手元のタスクを解決すると仮定します)。

于 2010-02-24T01:31:59.690 に答える