TMonitor.Pulse против TMonitor.PulseAll - PullRequest
5 голосов
/ 06 мая 2011

Delphi Docwiki объясняет, что Pulse уведомляет следующий поток в очереди ожидания, что он сможет заблокировать указанный объект, как только вызывающий поток освободит объект. PulseAll сигнализирует все потоки в очереди ожидания.

I найдено этот код, который использует Pulse в реализации многопоточной очереди, и, учитывая приведенное выше определение, считает, что PulseAll должениспользовать или спросить по-другому: когда правильно использовать Pulse вместо PulseAll?(Где основной вопрос: как я могу быть уверен, что «следующий поток в очереди» всегда является потоком, который должен быть уведомлен, кроме как в тривиальных случаях, когда всего только два потока, или код может безопасноПредположим, что единственный ожидающий поток - это поток, который должен быть nofified / 'pulsed')?

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 () и notifyAll () снова


Обновление: вопрос Java, связанный выше, имеет один интересный ответ, который показывает, как может возникнуть тупик даже в приложении производителя / потребителя, которое имеет только дваметоды, положить и получить, и который использует notify () (Java-аналог Pulse ()): Java: notify () и notifyAll () сначала

Ответ содержитрекомендация

Если вы не уверены, какой из них использовать, используйте notifyAll.

1 Ответ

1 голос
/ 06 мая 2011

В традиционной очереди производителя / потребителя каждый потребительский поток снимает один элемент с очереди.Когда вы ставите в очередь один элемент, вам нужно только разбудить один потребительский поток.Поскольку любой из потребительских потоков может справиться с задачей, не имеет значения, какой из них проснулся, пока он есть.Таким образом, достаточно вызова Pulse() вместо PulseAll().

...