2

我正在使用一个简单的静态线程池,其中有 4 个线程,每个线程都有一个队列,用于处理字符串列表中的各个行。在每个线程完成其队列中的一个请求后,它会同步一个事件,该事件在父线程中处理。这是通过在完成DoComplete()后调用来完成的,如下所示:

procedure TDecoderThread.DoComplete(const Line: Integer; const Text: String);
begin
  FLine:= Line;
  FText:= Text;
  Synchronize(SYNC_OnComplete);
end;

procedure TDecoderThread.SYNC_OnComplete;
begin
  if assigned(FOnComplete) then
    FOnComplete(Self, FText, FLine); //Triggers event which is handled in parent thread
end;

另一方面,在它们的父线程中,这些事件通过以下过程处理:

procedure TDecoder.ThreadComplete(Sender: TDecoderThread; const Text: String;
  const Line: Integer);
begin
  FStrings[Line]:= Text; //Updates the original line in the list with the new text
end;

由于我有 4 个不同的线程,每个线程都可能OnComplete()同时调用这个事件,我是否还需要担心线程保护这个FStrings: TStringsOnComplete()写入此字符串列表时,两个线程同时触发其事件是否会导致其父线程中的死锁?或者主线程是否足够聪明,可以等到其中一个完成后再处理另一个?

PS - 是的,这个小项目是试图回答其他人在 SO 上提出的另一个先前的问题,得到的答案大不相同,但为了让自己更熟悉多线程,我还是继续这个示例项目.

4

1 回答 1

4

由于OnComplete事件是由 触发的Synchronize(),因此您不需要在FStrings列表周围使用线程安全锁,因为对列表的所有访问都是通过主线程委托的,因此一次OnComplete只能实际运行一个事件处理程序。如果您不使用,则如果正在添加/删除项目并因此重新分配列表内存,或者如果其他线程正在从 读取值,而线程仍在运行,则Synchronize()需要这样的锁定。如果处理线程是唯一访问的线程,则不会存在并发访问单个项目的风险,因此不需要锁。FStringsFStringsFStrings

于 2012-07-06T01:06:00.740 回答