私は、整数はスレッドセーフであるという誤った仮定で、いくつかのスレッド化コードを書きました。それらはそうですが、私の使用はスレッドセーフではないようです。スレッド数を保持するためにグローバル整数 ThreadCount を使用しています。スレッドの作成中に、ThreadCount をインクリメントします。スレッドの破棄中に、デクリメントします。すべてのスレッドの作成が完了したら、それらが完了するのを待ち (ThreadCount が 0 になるはずです)、最終レポートを作成して終了します。
ただし、ログの事後調査ですべてのスレッドが実行されて完了したことが示されている場合でも、0 にならないことがあります (5%)。したがって、すべての兆候は、ThreadCount が踏みにじられていることを示しています。これは整数なので、これは不可能だと自分に言い聞かせてきました。私は単に inc/dec を使用しています。
ここにいくつかの関連コードがあります:
var // global
ThreadCount : integer; // Number of active threads
...
constructor TTiesUpsertThread.Create(const CmdStr : string);
begin
inherited create(false);
Self.FreeOnTerminate := true;
...
Inc(ThreadCount); // Number of threads created. Used for throttling.
end;
destructor TTiesUpsertThread.Destroy;
begin
inherited destroy;
Dec(ThreadCount); // When it reaches 0, the overall job is done.
end;
...
//down at the end of the main routine:
while (ThreadCount > 0) do // Sometimes this doesn't ever end.
begin
SpinWheels('.'); // sleeps for 1000ms and writes dots... to console
end;
私の問題は inc/dec にあると思います。2 つ以上の dec() が同時にヒットし、両方が同じ値を読み取る衝突が発生していると思うので、同じ値に置き換えます。例: ThreadCount = 5 で、2 つのスレッドが同時に終了した場合、両方とも 5 を読み取り、4 に置き換えます。ただし、新しい値は 3 にする必要があります。
テスト環境 (異なるハードウェア、トポロジ、負荷など) ではこれが問題になることは決してないので、このソリューションをビジネス ユニットに「売り込む」前に、これが問題である可能性が高いことを確認したいと考えています。
これが私の問題である場合、重要な選択を使用して inc/dec を保護しますか?
ご覧いただきありがとうございます。