根据 Go 博客,
映射对于并发使用是不安全的:它没有定义当你同时读取和写入它们时会发生什么。如果您需要从并发执行的 goroutine 读取和写入映射,则访问必须通过某种同步机制进行调解。 (来源: https ://blog.golang.org/go-maps-in-action)
谁能详细说明一下?并发读取操作似乎跨例程是允许的,但如果尝试读取和写入同一键,则并发读取/写入操作可能会产生竞争条件。
在某些情况下能否降低最后的风险?例如:
- 函数 A 生成 k 并设置 m[k]=0。这是 A 唯一一次写入映射 m。已知 k 不在 m 中。
- A 将 k 传递给同时运行的函数 B
- A 然后读取 m[k]。如果 m[k]==0,它等待,只有当 m[k]!=0 时才继续
- B 在地图中寻找 k。如果找到它,B 将 m[k] 设置为某个正整数。如果没有,它会一直等到 k 在 m 中。
这不是代码(显然),但我认为它显示了一个案例的轮廓,即使 A 和 B 都尝试访问 m 也不会有竞争条件,或者如果有竞争条件也不重要,因为额外的约束。
原文由 John D. 发布,翻译遵循 CC BY-SA 4.0 许可协议
在Golang 1.6之前,并发读是可以的,并发写是不行的,但是写并发读是可以的。从 Golang 1.6 开始,map 在写入时无法读取。所以在 Golang 1.6 之后,并发访问映射应该是这样的:
或者您将收到以下错误:
添加:
您可以使用
go run -race race.go
检测比赛更改
read
功能:另一个选择:
正如我们所知,
map
由桶实现,sync.RWMutex
将锁定所有桶。 并发映射 使用fnv32
对密钥进行分片,每个桶使用一个sync.RWMutex
。