マップから削除できるライターを含め、ライターが同時に存在するマップにまたがる場合m
、これを行うのはスレッドセーフではありませんか?:
for k, v := range m { ... }
スレッドセーフだと思っています。他の可能性のあるライターが値v
を読み取っているときに値を変更しないようにする必要があります。また、(ミューテックスを使用している場合、ロックは別の手順であるため)キーk
がまだマップにあることを確認します。 。例えば:
for k := range m {
m.mutex.RLock()
v, found := m[k]
m.mutex.RUnlock()
if found {
... // process v
}
}
m
(他のライターが変更する前に書き込みロックしていると仮定しv
ます。)より良い方法はありますか?
編集して追加:マップがスレッドセーフではないことを認識しています。ただし、http: //golang.org/ref/spec#For_statementsのGo仕様によると、これらは1つの方法でスレッドセーフです(「まだ到達していないマップエントリが反復中に削除された場合」を検索してください)。このページは、を使用するコードrange
が、他のゴルーチンがマップに挿入したり、マップから削除したりすることを気にする必要がないことを示しています。私の質問は、このスレッドセーフネスはに拡張されているので、使用するだけで読み取りv
を行うことができますか?v
for k, v := range m
そして他のスレッドセーフなメカニズムはありませんか?アプリを強制的にクラッシュさせて動作しないことを証明するためのテストコードを作成しましたが、スレッドセーフでないコードを露骨に実行していても(ロックメカニズムがない状態で同じマップ値を猛烈に変更するゴルーチンがたくさんあります)、できませんでしたクラッシュに行く!