如何等待多个 goroutine 完成?


package main
var fooRunning = false
var barRunning = false
func foo() {
fooRunning = true
defer func() { fooRunning = false }()
if barRunning {
// wait for bar() to finish
}
...
}
func bar() {
barRunning = true
defer func() { barRunning = false }()
if fooRunning {
// wait for foo() to finish
}
...
}

就我而言,如果我们运行go foo()它应该等待bar()完成,反之亦然。最好的方法是什么?请注意,它们也可以独立执行。

任何具体设计都无法安全地满足您的要求。按照规定,您说foobar可以在并发 goroutines 中运行,如果其中一个或两个都已启动,则另一个应该等待它们都完成。不过,这太弱了。如果foo开始然后完成,但bar尚未开始运行,会发生什么情况?如果bar根本就不跑怎么办?或者,如果bar运行,但foo永远不会运行怎么办?

您是否要求foobar都必须启动和完成才能使您的程序正确?如果是这样,我可以猜到你的意思是开出什么:你想要一个屏障,等待他们俩完成,然后再继续。

package main
import (
"fmt"
"sync"
"time"
)
func foo() {
fmt.Println("foo")
}
func bar() {
fmt.Println("bar")
}
func within(wg *sync.WaitGroup, f func()) {
wg.Add(1)
go func() {
defer wg.Done()
f()
}()
}
func main() {
var wg sync.WaitGroup
within(&wg, foo)
within(&wg, bar)
wg.Wait()
fmt.Println("Both foo and bar completed.")
}

(操场上的例子)

请注意,在这里,foobar都不是相互感知的;只有它们的调用者是,以便协调两个调用。

你最初的尝试可能会引导你走上使foobar关闭或接受参数的道路sync.WaitGroup,每个函数首先将自己添加到组中并在退出之前等待它。那条路就是疯狂。

如果foobar有机会将自身添加到WaitGroup之前启动和完成,foo将在bar之前退出,即使你可以声称它们一直在并发运行,或者相反,bar运行foo可以注册其活动状态。同样,由于这是程序的一个指定不佳的方面,我建议您改为关注更高级别的障碍,而不是这两个函数的相互依赖。

您可以使用频道!正如我记得从我生锈的去,这将给出:

func foo() {
c := make(chan int)
go bar(c)
<-c
}

和酒吧

func bar(c chan int) {
// do stuff here
c <- 0
}

最新更新