2 回答
TA贡献1946条经验 获得超3个赞
文档指出,“如果重用 a 来等待多组独立的事件,则必须在所有以前的 Wait 调用返回后进行新的 Add 调用”WaitGroup
在呼叫其他 goroutine 之前,您正在呼叫某些 goroutine,这是不允许的,如文档所述。在你开始所有这些戈鲁廷之前,你需要打电话,你还不如叫一次,wg.Done()wg.Add(1)wg.Addwg.Add(1000)
你的其他代码工作的原因是它从不调用,你有wg.Done()
if true {
return nil
}
defer wg.Done()
因此,您始终返回而不到达 defer 语句,因此永远不会对 进行任何调用。wg.Done()
请执行下列操作:
func callWorker(i int){
fmt.Println("Main: Starting worker", i)
// you cannot call Add here because Done has been called in other goroutines
go worker(&wg, i)
wg.Wait()
}
func main() {
wg.Add(1000) // <---- You must call Add before Done is called in any goroutine
for i := 0; i < 1000; i++ {
go callWorker(i)
}
time.Sleep(time.Second * 60)
fmt.Println("Main: Completed")
}
TA贡献1802条经验 获得超5个赞
问题是,如果在等待组上调用,则不允许重用此等待组并再次调用它,直到返回调用(请参阅文档)。在此程序中,调用工作函数本身就是一个 go 例程,所有调用工作函数都同时运行。在没有等待对方的情况下,他们试图在上一个电话未完成时打电话。Wait()Add()Wait()Add()Wait()
第一个工作线程生成结果时没有错误,因为他们的调用在下一个调用(一个经典的竞争条件)之前幸运地返回。Wait()Add()
如果您希望工作线程同时运行,则必须移动并退出调用工作器函数。 必须在 for 循环之后调用。并且应该在调用工作之前在循环内调用,否则程序将在callWorker有机会向等待组添加某些内容之前完成,因此无需等待。不需要时间。睡在里面,太。Wait()Add()Wait()Add()Wait()main()
func main() {
for i := 0; i < 1000; i++ {
wg.Add(1)
go callWorker(i)
}
wg.Wait()
fmt.Println("Main: Waiting for workers to finish")
fmt.Println("Main: Completed")
}
- 2 回答
- 0 关注
- 80 浏览
添加回答
举报