【发布时间】:2019-04-17 15:23:49
【问题描述】:
我想知道是否有办法在并发读/写期间仅锁定映射中的索引。如果答案很明显,我对 Golang 和并行性很抱歉。
func Check(a, b []string) map[string]int {
var res = make(map[string]int)
go func() {
for _, v := range a {
res[v]++
}
}()
go func() {
for _, v := range b {
res[v]++
}
}()
return res
}
由于并发映射读/写,最终这段代码会出现恐慌。所以我们应该添加互斥锁来锁定地图。
var m sync.Mutex
go func() {
for _, v := range a {
m.Lock()
res[v]++
m.Unlock()
}
}()
go func() {
for _, v := range b {
m.Lock()
res[v]++
m.Unlock()
}
}()
但据我了解m.lock() 会锁定我的整个地图吗?锁定所有内容不是太多开销吗?这让我很烦恼,因为我认为这段代码可能不会比线性运行更快。我是否可以只锁定map["some key"] 的地图,以便我的第二个goroutine 仍然可以写入map["some other key"]?
【问题讨论】:
-
您不能只锁定地图的一个条目,因为编写另一个条目可能会导致内部重组,这也可能影响其他条目,包括您打算锁定的条目。
-
事实上你也不能锁定整个地图。您锁定互斥锁。互斥锁控制访问的内容完全取决于您如何使用它。您可以为映射中的每个键创建一个互斥体,这将允许您按条目锁定粒度,但正如 icza 指出的那样,这实际上并不能防止数据竞争。
-
谢谢!您的回复对我帮助很大!
标签: dictionary go concurrency parallel-processing mutex