Go の 'range' を使用したマップへの同時アクセス
「Go マップの動作」ブログ エントリでは、ドキュメントにはマップが次のように記述されています。 sync.RWMutex のような同期メカニズムを使用せずに同時に使用するのは安全ではありません。ただし、範囲反復によるアクセスが「読み取り」を構成するのか、それとも範囲キーワードに特定のロック要件があるのかは明確ではありません。
範囲の同時実行
範囲式は次のとおりです。ループが開始される前に 1 回評価されます。マップの場合、これは、反復中に新しいキーと値のペアが追加または削除される場合でも、マップ変数 (testMap など) が 1 回だけ評価されることを意味します。初期評価と反復自体が分離されているということは、反復の実行中に for ステートメントによってマップがアクセスされないことを意味します。
安全な反復
したがって、次のようになります。反復は同時アクセスに対して安全です:
func IterateMapKeys(iteratorChannel chan int) error { testMapLock.RLock() defer testMapLock.RUnlock() mySeq := testMapSequence for k, _ := range testMap { .... } return nil }
この設計により、次の場合にのみマップがロックされます。
同時変更
ただし、このタイプのロックは同時アクセスを防止するだけであり、同時変更は防止しません。反復の進行中であっても、別のゴルーチンが書き込みロックを取得してマップを変更する可能性があります。これを防ぐには、反復を通じてマップをロックしたままにする必要があります。
例
この例では、for ブロック内でのロック解除とロックの違いを示します。
func IterateMapKeys(iteratorChannel chan int) error { testMapLock.RLock() defer testMapLock.RUnlock() mySeq := testMapSequence for k, _ := range testMap { testMapLock.RUnlock() .... testMapLock.RLock() .... } return nil }
この例では、for ブロック内の読み取りロックを解放することで、同時変更と潜在的な可能性が可能になります。エラー。
結論
range キーワード自体は、マップへの同時アクセスの同期を提供しません。適切な同期メカニズム (sync.RWMutex など) を使用することは、同時反復と変更の安全性を確保するために非常に重要です。
以上がGo の「range」キーワードはマップへの同時アクセスに対して安全ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。