2011-06-28 15 views
0

私は2つのスレッド(ブーストスレッドライブラリを使用)とグローバルベクトルをWindows上に持っています(Visual Studio 2005)。私はスレッドを作成しました - 最初にファイル(vector.push_back(value))を読み込み、 "読み込みカウンター"を増やしています。もう1つはすでに読み込まれたデータを処理しています(2番目の "ポインタ"はすでに処理されたベクトルのインデックスを記憶しています)。処理は次のようなものですvector[i] = function(vector[i]);ベクトルを同時に読み書きすると例外が発生する

プログラムを起動すると、例外が発生します。Unhandled exception at 0x0041350c in program.exe: 0xC0000005: Access violation writing location 0x00b82214.読み取りカウンタの値がレコードの数より少なく(ファイルを読み込んでいます)、vector.size()が "readCounter + 1"ポインタ "+/- 2200(はるかに少ないカウンタを読み取り、空の値を読み取る際には問題ありません)...値は実行ごとに異なります(例外はスローされずにプログラムが終了する場合もあります)...

処理を削除すると行(vector[i] = function(vector[i]);)問題は発生しません...私は推測するので、ベクトルはスレッドセーフではありません。この問題を防ぐ方法を教えてください。

+0

は、ほとんどの場合に必要とされていない大きなオーバーヘッドが追加されます。 *標準ライブラリはスレッドセーフではないと常に仮定すべきです。 –

答えて

0

だから、ベクトルはスレッドセーフではありません。

もちろんstd :: vectorはスレッドセーフではありません(標準的なコンテナはスレッドセーフであることは保証されていませんが、すべてのメソッドはすべての正常な実装で再入可能であることが保証されています)。同期メカニズム(mutexなど)を使用する必要があります。

5

現在のバージョンの標準(C++ 03)はスレッドを認識しないため、STLコンテナがスレッドセーフであるかどうかは、特定の実装に完全に依存します。あなたのケースでは

は、あなたが

単一のオブジェクトが複数のスレッドから読み取るため、スレッドセーフであると述べているMSDNのthis pageを参照してください。例えば、オブジェクトAが与えられると、スレッド1からAを、スレッド2からAを同時に読み出すことは安全である。

1つのスレッドによって1つのオブジェクトが書き込まれている場合、同じスレッドまたは他のスレッド上のそのオブジェクトに対するすべての読み取りと書き込みを保護する必要があります。例えば、スレッド1がAに書き込んでいる場合は、オブジェクトAを与えられ、その後、スレッド2はこのように、あなたの読み取りを保護しなければならない/ミューテックスまたは一部を書き込みますA.

に読み取りまたは書き込みを防止しなければなりません他の同期プリミティブ。 Boost.Thread(これはC++ 0xのスレッドサポートがベースとしているライブラリです)でマルチプラットフォームとC++に優しい実装を見つけることができます。ところで


あなたはVC++(例えば2003)の以前のバージョンを使用していた場合、それらのバージョンでは、マルチスレッドと利用できる標準ライブラリのsinglethreadバージョンの両方があることを覚えておいてください。アプリケーションでスレッドとCRT機能を使用する場合は、CRTのシングルスレッド版を使用しないでください。プロジェクトの設定をチェックして、正しいバージョンが選択されているかどうかを確認してください。

0

ベクターは成長可能なデータ構造です。もちろん、任意の大きなメモリを割り当てることはできませんので、実装は固定サイズのメモリ(構築時に設定可能)を割り当てます。あなたのベクトルにpush_back要素があるので、このスペースはいっぱいになります。それが事前に割り当てられたスペースの終わりに達すると、より大きなチャンク(通常は元のサイズの2倍)を割り当てて、その中のすべてのデータをコピーする必要があります。また、チャンクが始まるメモリ位置を更新し、古い割り当てられた領域を解放する必要があります。あなたはもうあなたに属していないメモリアドレスへのいくつかの値を書き込むしようとしている一方

...

あなたはそれはあなたがすべてのメモリを事前に割り当てることができます成長する方法を大わかっている場合は、それニーズ。これは、サイズを倍増させるので、何度も何度もコピーする必要がないという利点があります。

参照:物事はスレッドセーフ作るvector::vectorvector::capacityvector::reserve

+0

ベクトルが成長していなくても、更新されるとスレッドセーフであることが保証されていない内部状態を含んでいます。悪い結果の可能性は減りますが、排除されることはありません。 –

+0

保証はされていませんが、通常は正常に動作します(標準ではこれについて何も言わないので)...ベクトルのサイズを更新する必要がありますが、それは機械語に格納され、原子的である。 –

+0

サイズを更新することは不可解かもしれませんが、まだ問題になることがあります。例えば、新しい要素が挿入される前にサイズが更新されたとしますか?実装が次のコンパイラバージョンで変更される可能性がある場合、実装の詳細に頼らないことをお勧めします。 –

関連する問題