问题是updateWorker
goroutine 都从以下位置收集结果hits
通道(到目前为止一切顺利),并且它们都将结果存储到temp
局部变数不同步。这是不行的。
从多个 goroutine(其中至少有一个是写入)对所有变量的访问必须同步。
如果您在启用竞争检测器的情况下运行它,它会尖叫着数据竞争(go run -race app.go
).
如果减少数量,它会立即产生有效结果updateWorker
goroutine 设为 1,因为这样我们就消除了应用程序的单一数据竞争源:
for updateWorker := 1; updateWorker <= 1; updateWorker++ {
// ...
}
如果你想保留多个updateWorker
goroutine,它们对共享的访问temp
变量必须同步。
With a sync.Mutex https://golang.org/pkg/sync/#Mutex:
var (
mu sync.Mutex
temp []string
)
for updateWorker := 1; updateWorker <= 4; updateWorker++ {
wg.Add(1)
go func() {
for hit := range hits {
mu.Lock()
temp = append(temp, hit)
mu.Unlock()
}
wg.Done()
return
}()
}
另请注意,在这个简单的示例中,使用多个updateWorker
对于 goroutine,添加上述同步(锁定)甚至会使其性能低于仅使用其中之一的性能。
为了正确分配工作和收集结果,请查看以下答案:这是 Go 中惯用的工作线程池吗? https://stackoverflow.com/questions/38170852/is-this-an-idiomatic-worker-thread-pool-in-go/38172204#38172204