9

私は 1 つの std::list<> コンテナーとこれらのスレッドを持っています:

  • 要素を無期限に追加する 1 つのライター スレッド。

  • 使用可能なときに要素を読み取って削除する 1 つのリーダー/ライター スレッド。

  • コンテナーの SIZE にアクセスする複数のリーダー スレッド (size() メソッドを使用)

最初の 2 つのスレッドからリストへのアクセスを保護する通常のミューテックスがあります。私の質問は、サイズ リーダー スレッドもこのミューテックスを取得する必要があるかどうかです。読み取り/書き込みミューテックスを使用する必要がありますか?

Visual C++ 6 を使用する Windows 環境にいます。

更新:答えはまだはっきりしていないようです。主な疑問を要約すると: 正確な値を必要としない (つまり、 +/- 1 変動)? 競合状態により、size() 呼び出しが無効な値 (つまり、適切な値とはまったく関係のない値) を返すようになるのはなぜですか?

回答: 一般に、競合状態を回避するためにリーダー スレッドを保護する必要があります。それにもかかわらず、私の意見では、アップデートで上記の質問のいくつかはまだ答えられていません.

前もって感謝します!

回答ありがとうございます。

4

8 に答える 8

10

はい、読み取りスレッドにはある種のミューテックス制御が必要です。そうしないと、書き込みによってその下から物事が変更されます。

リーダー/ライター ミューテックスで十分です。しかし、厳密に言えば、これは実装固有の問題です。コード内で読み取り専用の const オブジェクトであっても、実装に変更可能なメンバーが含まれている可能性があります。

于 2008-10-09T14:49:21.150 に答える
2

Intel の Open Source Threading Building Blocksライブラリが提供する並行コンテナーをチェックアウトします。いくつかの例については、コード サンプル ページの「コンテナー スニペット」を参照してください。ベクトル、ハッシュマップ、およびキュー用の並行/スレッドセーフコンテナーがあります。

于 2008-10-09T15:18:12.293 に答える
1

一部の SLT 実装では、呼び出し時にサイズが計算される可能性があることを考慮する必要があります。
これを克服するために、新しい変数を定義できます

volatile unsigned int ContainerSize = 0;

すでに保護されている更新呼び出し内でのみ変数を更新しますが、保護なしで変数を読み取ったりテストしたりできます (正確な値は必要ないことを考慮してください)。

于 2008-10-28T10:01:17.117 に答える
1

クロスプラットフォームでスレッドを処理する良い方法がないため、STL コンテナーがスレッドセーフであるとは思えません。size() の呼び出しは単純ですが、それでも保護する必要があります。

これは、読み取り/書き込みロックを使用するのに最適な場所のように思えます。

于 2008-10-09T14:50:16.873 に答える
0

size() が安全かどうか (提供する「安全」の定義について) は、実装に依存します。スレッド ライブラリと C ランタイムのバージョンの最適化レベルでのコンパイラのバージョンについて、プラットフォームでカバーされている場合でも、この方法でコーディングしないでください。それはあなたをバイトに戻すでしょう、そしてデバッグするのは地獄です. あなたは失敗する準備をしています。

于 2008-10-29T03:09:27.837 に答える
0

はい。シリアル アクセスを強制するクラスで STL ライブラリをラップすることをお勧めします。または、既にデバッグされている同様のクラスを見つけます。

于 2008-10-09T14:51:27.573 に答える
0

私はノーと言うつもりです。この場合。

ミューテックスがないと、アイテムが追加または削除されると、 size() が間違った値を返すことがあります。これが受け入れられる場合は、それを選択してください。

ただし、読者がリストの正確なサイズを知る必要があるときにリストの正確なサイズが必要な場合は、add および erase 呼び出しの周りにあるクリティカル セクションに加えて、すべての size 呼び出しの周りにクリティカル セクションを配置する必要があります。

PS。VC6 size() は単純に _Size 内部メンバーを返すため、特定の実装ではミューテックスがなくても問題はありませんが、2 番目の要素が追加されているときに 1 が返される場合や、その逆の場合があります。

PPS。誰かが RW ロックについて言及しましたが、これは良いことです。後でリスト オブジェクトにアクセスしたい場合は特にそうです。ミューテックスを Boost::shared_mutex に変更すると有益です。ただし、呼び出しているのが size() だけの場合、ミューテックスはまったく必要ありません。

于 2008-10-09T15:04:33.833 に答える
0

The STL in VC++ version 6 is not thread-safe, see this recent question. So it seems your question is a bit irrelevant. Even if you did everything right, you may still have problems.

于 2008-10-10T15:05:42.057 に答える