在Go 中使用「範圍」並發存取地圖
在「Go 地圖實際應用」部落格文章中,文件指出映射如果沒有像sync.RWMutex這樣的同步機制,並發使用是不安全的。但是,目前尚不清楚透過範圍迭代進行的存取是否構成“讀取”,或者範圍關鍵字是否有特定的鎖定要求。
範圍的並發
範圍表達式為在循環開始之前評估一次。對於映射,這意味著映射變數(例如 testMap)僅計算一次,即使在迭代期間可能會新增或刪除新的鍵值對。初始評估和迭代本身之間的這種分離意味著執行迭代時 for 語句不會存取映射。
安全迭代
因此,以下迭代對於並發訪問是安全的:
func IterateMapKeys(iteratorChannel chan int) error { testMapLock.RLock() defer testMapLock.RUnlock() mySeq := testMapSequence for k, _ := range testMap { .... } return nil }
這種設計確保地圖僅在必要時才訪問被鎖定,同時允許並發訪問其他
並發修改
但是,這種類型的鎖定僅阻止並發訪問,而不能阻止並發修改。即使迭代正在進行時,另一個 goroutine 也可能會取得寫鎖並修改映射。為了防止這種情況,地圖應該在整個迭代過程中保持鎖定狀態。
範例
此範例示範了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中文網其他相關文章!