go - 引擎盖下发生了什么,所以地图的这种并发使用是活泼的
问题描述
在下面的示例中,竞态检测器将触发错误。不过,我对此很好,因为它不会更改键、地图标题(如果我可以说的话),我很难弄清楚比赛的原因是什么。我根本不明白引擎盖下发生了什么,因此发出了种族检测。
package main
import (
"fmt"
"sync"
)
// scores holds values incremented by multiple goroutines.
var scores = make(map[string]int)
func main() {
var wg sync.WaitGroup
wg.Add(2)
scores["A"] = 0
scores["B"] = 0
go func() {
for i := 0; i < 1000; i++ {
// if _, ok := scores["A"]; !ok {
// scores["A"] = 1
// } else {
scores["A"]++
// }
}
wg.Done()
}()
go func() {
for i := 0; i < 1000; i++ {
scores["B"]++ // Line 28
}
wg.Done()
}()
wg.Wait()
fmt.Println("Final scores:", scores)
}
解决方案
映射值是不可寻址的,因此递增整数值需要将它们写回映射本身。
线
scores["A"]++
相当于
tmp := scores["A"]
scores["A"] = tmp + 1
如果您使用指针使整数值可寻址,并在分派 goroutine 之前分配所有键,您可以看到地图本身不再存在竞争:
var scores = make(map[string]*int)
func main() {
var wg sync.WaitGroup
wg.Add(2)
scores["A"] = new(int)
scores["B"] = new(int)
go func() {
for i := 0; i < 1000; i++ {
(*scores["A"])++
}
wg.Done()
}()
go func() {
for i := 0; i < 1000; i++ {
(*scores["B"])++
}
wg.Done()
}()
wg.Wait()
fmt.Println("Final scores:", scores)
}
推荐阅读
- dialogflow-es - 为什么 Dialogflow nodejs sdk“使用知识库检测意图”方法以 null 响应?(V2Beta)
- javascript - 如何在angularjs中刷新指令数据
- ansible - Ansible:更改=0
- kendo-ui - 剑道网格数字文本框编辑器值更改不更新模型
- canvas - 创建画布时,应用程序在某些时候崩溃
- jmeter - JMeter - 用户负载较高的状态码 404
- javascript - 为什么 0 && true echo 0 在 js 中?
- python - 使用 django 为数据库中的列计算具有相同值的连续行?
- php - Mysql 是否维护对其事务的任何引用?
- vb.net - 将数据源中的对象绑定到 datagridview 组合框 VB.Net