在 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中文网其他相关文章!