让线程等待其他对象中的条件

Make threads wait for conditon in other object

如果我想限制可以同时在一个词典中完成的线程查找的数量,该怎么做?并让线程休眠,直到它们可以访问词典。 IE。如果两个查找已经在并行进行,则其他查找必须等待,直到 LookupCount 小于二才执行。

TLexicon
  MaxLookups: Integer;
  LookupCount: Integer;

除了 TLexicon,我还创建了 TLookupJob,它应该在 TLookupThread 中执行。 LookupJob.Execute 过程调用词典查找并等待直到有响应。

因此,LookupThreads 必须休眠直到 Lexicon.LookupCount 小于 Lexicon.MaxLookups。为此,我在 LookupJob.Execute 中调用了 GoSleep(事件),LookupThread 的执行停止了。但是如何以及何时发出信号。其余的设计我不清楚。

这里可以用什么设计?

到目前为止我已经创建了一些类:

TLexicon - 具有 MaxLookups 和 LookupCount,以及一个 Lookup 函数。

LookupItem - 包含 LookupWord 和 Response。传递给 Lexicon.Lookup.

TLookupJob - 有一个 Execute 过程,加上 GoSleep 和一个使用睡眠事件的 WakeUp 过程。

LookupThread - 执行 LookupJob

随时更改设计。

如果您的目标是 Windows 平台,WinAPI 会提供合适的同步功能。参见 CreateSemaphore, ReleaseSemaphore, WaitForSingleObject。 (当然,独立于平台的选项可能是首选,但这在某些环境中可能仍然有用。)

当你create/initialise你的词典时,创建一个信号量如下:

FSemaphoreHandle := CreateSemaphore(nil, MaxLookups, MaxLookups, nil);

然后在进行查找时,使用信号量来限制有多少线程同时进入查找例程的主体。

function TLexicon.Lookup(...): ...;
begin
  //The wait function will block if the current counter = 0 and wait
  //until another thread releases a counter.
  WaitForSingleObject(FSemaphoreHandle, <timeout>);
  //When the wait function returns (assuming due to semaphore count
  //available and not timeout), the current counter of the semaphore
  //is decreased. This mechanism limits the number of threads that
  //can get past the wait funtion.
  try
    //Do lookup
  finally
    //By releasing the semaphore, the current counter is increased again,
    //allowing a blocked thread to get past the wait function.
    ReleaseSemaphore(FSemaphoreHandle, 1, nil);
  end;
end;

最后,不要忘记 CloseHandle 完成词典后。

注意:这是一个简单的示例。不要忘记添加适当的错误检查。例如。 WaitForSingleObject 指示是否可以获取信号量。