让线程在其他对象中等待conditon

Rim*_*ire 0 delphi multithreading freepascal lazarus

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

TLexicon
  MaxLookups: Integer;
  LookupCount: Integer;
Run Code Online (Sandbox Code Playgroud)

除了TLexicon之外,我创建了TLookupJob,它可以在TLookupThread中执行.LookupJob.Execute过程调用词典上的查找并等待直到有响应.

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

这里可以使用什么设计?

到目前为止,我已经创建了许多类:

TLexicon - 具有MaxLookups和LookupCount,以及查找功能.

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

TLookupJob - 具有执行过程,以及GoSleep使用事件进行睡眠的WakeUp过程.

LookupThread - 执行LookupJob

随意改变设计.

Dis*_*ned 5

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

创建/初始化词典时,请按如下方式创建sempaphore:

FSemaphoreHandle := CreateSemaphore(nil, MaxLookups, MaxLookups, nil);
Run Code Online (Sandbox Code Playgroud)

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

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;
Run Code Online (Sandbox Code Playgroud)

最后,当你完成词典时,不要忘记CloseHandle.

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

  • Delphi提供[`System.SyncObjs.TSemaphore`](http://docwiki.embarcadero.com/Libraries/XE8/en/System.SyncObjs.TSemaphore),它封装了Windows信号量API. (2认同)