38

std :: map内のオブジェクトへの参照はスレッドセーフですか?

std::map< std::string, Object >   _objects;

マップは多くのスレッドから変更でき、このアクセスは同期されますが、値(Object&)への参照は1つのインスタンスとスレッドからのみアクセスできます。オブジェクトを使用した書き込み操作はありますか?別のスレッドがマップにアイテムを追加する場合は安全ですか?再割り当てしますか?

4

2 に答える 2

37

C ++ 11標準constは、コンテナーへのメソッドアクセスが異なるスレッドから安全であることを保証します(つまり、両方がconstメソッドを使用します)。

さらに、[container.requirements.dataraces]は次のように述べています

含まれているオブジェクトのコンテンツが同じシーケンスの異なる要素にある場合、データの競合を回避するための実装が必要です。vector<bool>

言い換えれば、vector<bool>個別のコンテンツを変更することを除いて、データの競合ではありません。

ここで、あるスレッドが別のスレッドで使用されているイテレーターを無効にした場合、これは明らかにデータ競合です(結果として未定義の動作になります)。const1つのスレッドがコンテナに非アクセスし、別のスレッドがアクセスするconst場合、それはデータ競合(および未定義の動作)です。(注:constマルチスレッドの目的で多くの関数が「考慮」されます。これには、非イテレータ を返すという理由だけでなく、スレッドの安全上の理由から、この一連の疑似関数beginに含まれるend他の関数(およびメソッド)が含まれます。 、およびなどを除く-23.2.2.1)。constconst[]constmapunordered_set

ただし、コンテナ内の要素への参照があり、別のスレッドでその参照を無効にせず、別のスレッドでその要素に書き込まない操作を行う場合は、その参照から安全に読み取ることができるようです。同様に、他のスレッドが要素から読み取ることさえない場合、その要素に書き込むことで未定義の動作が発生することはありません。

標準リファレンスの場合、17.6.5.9.5は、標準ライブラリの関数が暴走したり、要素を不必要に読み書きしたりしないことを保証しているようです。

つまり、簡単な答えです。他のスレッドがの特定のエントリを直接混乱させない限り、安全ですmap

于 2013-02-25T12:58:36.253 に答える
15

マップ内の要素は安定しており、要素がマップから消去されない限り、移動または無効化されません。特定のオブジェクトに書き込んでいるスレッドが1つだけで、マップ自体への変更が正しく同期されている場合は、安全だと思います。実際には安全だと思いますし、理論的にも安全だと思います。

この標準は、[container.requirements.dataraces]内の異なるスレッドによって個別の要素を変更できることを保証します。

(17.6.5.9)にも関わらず、同じシーケンス内の異なる要素に含まれるオブジェクトのコンテンツが、を除いて同時にvector<bool>変更される場合、データの競合を回避するための実装が必要です。

これにより、要素の変更のみが可能になり、要素の変更中に新しい要素がマップに挿入されることはありません。などの一部のコンテナでは、ベクトル自体を変更すると、要素を再割り当てして移動することで要素を変更することもありますが、[associative.reqmts] / 9は、既存の要素を無効にしないことをstd::vector保証します。std::map

std::mapその要素の2番目のメンバー(つまり)にアクセスするためにのメンバー関数は必要ないので、mapped_type[res.on.data.races] / 5は、マップを変更するときに他のスレッドがそのメンバーへの書き込みと競合しないと言っていると思います。(パズルの最後のピースをくれたYakkに感謝します)

于 2013-02-25T12:43:53.550 に答える