问题在于,
updateWorkergoroutine都从
hits通道收集了结果(到目前为止很好),并且它们都将结果存储在未 同步*
的
temp本地变量中。这不行。 *
必须同步访问多个goroutine中的所有变量(其中至少有一个是写操作)。
如果在启用了竞争检测器的情况下运行它,它会发出有关数据竞争的尖叫(
go run -race app.go)。
如果将
updateWorkergoroutine 的数量减少到1,它将立即产生有效的结果,因为这样我们就消除了应用程序的单个数据争用源:
for updateWorker := 1; updateWorker <= 1; updateWorker++ { // ...}如果要保留多个
updateWorkergoroutine,则
temp必须同步它们对共享变量的访问。
带有
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 }()}还要注意,在这个简单的示例中,通过使用多个
updateWorkergoroutine并不会获得任何好处,与仅使用其中的一个相比,添加上述同步(锁定)甚至会使性能降低。



