5

Delphi Docwiki では、呼び出しスレッドがオブジェクトを解放するとすぐに、指定されたオブジェクトをロックできるようになることを、Pulseが待機キュー内の次のスレッドに通知すると説明しています。PulseAllは、待機キュー内のすべてのスレッドにシグナルを送ります。

スレッド化されたキューの実装で Pulse を使用するこのコードを見つけました。上記の定義を考えると、PulseAll を使用するか、別の方法で質問する必要があると思います。PulseAll の代わりに Pulse を使用するのはいつですか? (基本的な質問は次のとおりです。「キュー内の次のスレッド」が常に通知する必要があるスレッドであることをどのように確認できますか。ただし、スレッドが合計で 2 つしかない場合や、コードが安全に実行できる場合を除きます。唯一の待機中のスレッドは、通知/「パルス」が必要なスレッドであると仮定します)?

function TSimpleThreadedQueue.Enqueue(const Item: T; Timeout: LongWord): TWaitResult;
begin
  if Closed then Exit(wrAbandoned);
  if not TMonitor.Enter(FQueue, Timeout) then Exit(wrTimeout);
  try
    if Closed then Exit(wrAbandoned);
    FQueue.Enqueue(Item);
    TMonitor.Pulse(FQueue);
    Result := wrSignaled;
  finally
    TMonitor.Exit(FQueue);
  end;
end;

Java 言語の対応する同期メソッドについて、次の質問を見つけました: Java: notify() vs. notifyAll() all over again


更新: 上記の Java の質問には興味深い回答が 1 つあります。これは、put と get の 2 つのメソッドしかなく、notify() (Pulse() の Java 版) を使用するプロデューサー/コンシューマー アプリケーションでもデッドロックが発生する可能性があることを示しています。 : Java: notify() 対 notifyAll() の繰り返し

回答には推奨事項が含まれています

どちらを使用すればよいかわからない場合は、 を使用してnotifyAllください。

4

1 に答える 1

1

従来のプロデューサー/コンシューマーキューでは、各コンシューマースレッドがキューから1つのアイテムを取り出します。単一のアイテムをキューに入れるときは、単一​​のコンシューマースレッドをウェイクアップするだけで済みます。どのコンシューマースレッドもタスクを処理できるため、どちらがウェイクアップされているかは関係ありません。Pulse()したがって、ではなくへの呼び出しでPulseAll()十分です。

于 2011-05-06T12:59:40.847 に答える