備忘録的投稿です。
std::mapの利用でスレッドセーフを犯していた
mapへの要素の追加[]=、削除erase()については最低限mutexを使っていたが、
当然のことながら、同時に起こりうる読み込み操作においてもmutexを使用しないといけない。
書き込みは稀で、ほとんどが読み込みなんですけど...
全て読み込み操作ならば、スレッドセーフ。
100回中、99回が読み込みで1回が書き込みのような場合、
この「1回」のためにmutexを使わないといけないのはばかばかしい。
こういう細かい対応については、ライブラリに頼らず自分で実装したほうがよい。
例えば、要素のインデックスを管理するものと、要素をそれぞれ別のオブジェクトとして作る。
追加、削除に関してのみ管理オブジェクトをmutexを使って変更すればよい。
ある要素のポインタ(アドレス)が他の要素が追加されようが削除されようが不変なら各スレッド間でその要素を自由に読んでよいし、さらに
要素が1つのスレッドからしかアクセスされないならば、mutexを使わずに値を変更してもよい。
結論
結局の所、この辺の最適化はケースバイケースであってこれといった正解はない。
とにかく、実装がわからないものに対してはスレッドセーフを忠実に守るようなコードを書かなくてはいけないというのが本日の教訓。