1

私は次のことを計画しています:

消費される事前構築済みオブジェクトの両端キューを保存します。メインスレッドは、これらのオブジェクトをあちこちで消費する可能性があります。ロギングや、タイムクリティカルではないが高価なものに使用される別のジャンクスレッドがあります。ビルド済みのオブジェクトが少なくなったら、ジャンク スレッドに補充します。

ここで私の質問は、ここで競合状態になるのでしょうか? 技術的には、1 つのスレッドが前面からオブジェクトを消費し、別のスレッドがオブジェクトを背面に押し込みます。サイズがゼロにならなければ問題ないはずです。私に関係する唯一のことは、この両端キューの「サイズ」です。整数の「サイズ」変数を STL コンテナーに格納しますか? そのサイズ変数を変更して競合状態を導入する必要がありますか?

この問題を解決する最善の方法は何ですか? メイン スレッドはパフォーマンスが重要であるため、ロックを使用したくありません (最初にこれらのオブジェクトを事前にビルドした理由です!)

4

4 に答える 4

8

STL コンテナーはスレッド セーフではありません。具体的には、deque 要素は通常、短い配列のチェーンに格納され、そのチェーンは deque を操作するときに変更されるため、混乱する余地がたくさんあります。

于 2012-06-01T13:35:39.043 に答える
4

もう 1 つのオプションは、読み取り用と書き込み用の 2 つの deque を持つことです。メインスレッドが読み取り、もう一方が書き込みます。読み取り両端キューが空の場合、両端キューを切り替えます (2 つのポインタを移動するだけです)。これにはロックが必要ですが、たまにしかありません。

コンシューマ スレッドがスイッチを駆動するため、スイッチを切り替えるときにロックを実行するだけで済みます。プロデューサースレッドは、書き込みの途中で切り替えが発生した場合に備えて、書き込みごとにロックする必要がありますが、あなたが言及したように、コンシューマーはパフォーマンスの重要性が低いため、心配する必要はありません.

他の人が言及しているように、ロックなしに関してあなたが提案していることは確かに危険です。

于 2012-06-01T13:36:12.507 に答える
1

@sharptooth が述べたように、STL コンテナーはスレッドセーフではありません。C++11 対応のコンパイラを使用していますか? その場合、アトミック型を使用してロックフリー キューを実装できます。それ以外の場合は、コンペアアンドスワップにアセンブラーを使用するか、プラットフォーム固有の API を使用する必要があります (こちらを参照)。これを行う方法については、この質問を参照してください。

標準スレッド同期を使用する場合のパフォーマンスを測定し、実際にロックフリー手法が必要かどうかを確認することを強調します。

于 2012-06-01T13:52:52.957 に答える
0

空でない場合でもデータ競合が発生しますdeque

スルー ロックへのすべてのアクセス (書き込みだけでなく) を保護するdequeか、マルチスレッド環境 (Microsoft などunbounded_buffer) でコンシューマ/プロデューサー モデル用に特別に設計されたキューを使用する必要があります。

于 2012-06-01T13:38:25.033 に答える