複数のスレッドが1つのマップオブジェクトにアクセスする場合でも、アクセスするこれらのスレッドのいずれかが同じキーを持たないことを確認できます。アクセスは次のようになります。
//find value by key
//if find
// erase the object or change the value
//else
// add new object of the key
操作によって同期の問題が発生しますか?</ p>
複数のスレッドが1つのマップオブジェクトにアクセスする場合でも、アクセスするこれらのスレッドのいずれかが同じキーを持たないことを確認できます。アクセスは次のようになります。
//find value by key
//if find
// erase the object or change the value
//else
// add new object of the key
操作によって同期の問題が発生しますか?</ p>
はい、適切な同期なしで同時更新を行うと、スレッドが異なるキーにアクセスしている場合でも、クラッシュが発生する可能性があります。これstd::map
はツリーに基づいており、ツリーのバランスが再調整されるため、一見無関係なキーを使用してノードの親に書き込みを行うことができます。
さらに、書き込み、またはロック解除+書き込み時のロックの検索と同時に読み取り専用アクセスを実行することは安全ではありません。ノードを更新または削除する可能性のあるスレッドがある場合は、書き込む前にすべてのリーダーをロックアウトする必要があります。
いずれかのスレッドがツリーに挿入されると、並行性の問題が発生します。STLmap
は、赤黒ツリーを使用して実装されます (または、少なくとも私はそれをよく知っています — 標準で赤黒ツリーが義務付けられているかどうかはわかりません)。赤黒ツリーは挿入時に再調整される可能性があり、スレッド間であらゆる種類の競合が発生します。
読み取り専用アクセス (絶対にライターなし) は問題ありませんが、読み取り専用でoperator[]
はないことに注意してください。新しい要素を追加する可能性があります。メソッドを使用しfind()
、反復子を取得して、自分で逆参照する必要があります。
ドキュメント(つまり、ISO C ++ 11標準)がスレッドセーフであると述べていない限り(そしてそうではない)、それだけです。限目。スレッドセーフではありません。
これを可能にするstd::mapの実装があるかもしれませんが、それは決して移植可能ではありません。
多くの場合、マップは赤黒木またはその他の自動バランシングデータ構造に基づいて構築されているため、構造を変更すると(キーの挿入や削除など)、リバランシングが発生します。
同期が正しく行われるようにするには、マップ上の読み取りおよび書き込み操作をミューテックスセマフォなどでラップする必要があります。