TMonitor.Pulse与TMonitor.PulseAll

时间:2011-05-06 12:53:35

标签: delphi pulse tmonitor

Delphi Docwiki解释说,Pulse通知等待队列中的下一个线程,一旦调用线程释放对象,它就能锁定指定的对象。 PulseAll发出等待队列中所有线程的信号。

I found此代码在线程队列实现中使用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() vs. notifyAll() all over again


更新:上面链接的Java问题有一个有趣的答案,它显示了即使在生成器/消费者应用程序中也会发生死锁,它只有两个方法,put和get,以及使用notify()(Pulse的Java对应物) ()):Java: notify() vs. notifyAll() all over again

答案包含建议

  

如果你不确定使用哪个,那么   使用notifyAll

1 个答案:

答案 0 :(得分:1)

在传统的生产者/消费者队列中,每个消费者线程从队列中取出一个项目。 当您将单个项目排入队列时,您只需要唤醒单个消费者线程。由于任何消费者线程都可以处理任务,因此无论哪一个被唤醒都是无关紧要的。因此,拨打Pulse()而不是PulseAll()就足够了。