2

私は単純な静的スレッドプールを使用しています。ここでは、文字列リストの個々の行を処理する4つのスレッドがあり、それぞれにキューがあります。各スレッドは、キュー内の要求の1つを完了すると、親スレッドで処理されるイベントを同期します。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;

OnComplete()私には4つの異なるスレッドがあり、それぞれが同時にこのイベントを呼び出す可能性があるので、スレッドがこれを保護することについても心配する必要がありますFStrings: TStringsか?2つのスレッドOnComplete()が同時にイベントをトリガーすると、この文字列リストに書き込むときに親スレッドでデッドロックが発生する可能性がありますか?または、メインスレッドは、一方が完了するまで待ってからもう一方を処理するのに十分なほど賢いでしょうか?

PS-はい、この小さなプロジェクトは、SOに関する他の誰かからの別の以前の質問に答える試みでしたが、答えは大きく異なりますが、マルチスレッドにもう少し慣れるために、とにかくこのサンプルプロジェクトを続けました。

4

1 に答える 1

4

OnCompleteイベントはによってトリガーされるため、リストへのすべてのアクセスはメインスレッドを介して委任されるため、リストのSynchronize()周りでスレッドセーフロックを使用する必要はありません。したがって、実際に実行できるイベントハンドラーは一度に1つだけです。を使用していない場合、アイテムが追加/削除されてリストメモリが再割り当てされる場合、またはスレッドの実行中に他のスレッドがから値を読み取る場合は、このようなロックが必要になります。アクセスするのが処理スレッドだけである場合、個々のアイテムに同時にアクセスするリスクはないため、ロックは必要ありません。FStringsOnCompleteSynchronize()FStringsFStringsFStrings

于 2012-07-06T01:06:00.740 に答える