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()
完成,反之亦然。最好的方法是什么?请注意,它们也可以独立执行。
任何具体设计都无法安全地满足您的要求。按照规定,您说foo
和bar
可以在并发 goroutines 中运行,如果其中一个或两个都已启动,则另一个应该等待它们都完成。不过,这太弱了。如果foo
开始然后完成,但bar
尚未开始运行,会发生什么情况?如果bar
根本就不跑怎么办?或者,如果bar
运行,但foo
永远不会运行怎么办?
您是否要求foo
和bar
都必须启动和完成才能使您的程序正确?如果是这样,我可以猜到你的意思是开出什么:你想要一个屏障,等待他们俩完成,然后再继续。
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.")
}
(操场上的例子)
请注意,在这里,foo
和bar
都不是相互感知的;只有它们的调用者是,以便协调两个调用。
你最初的尝试可能会引导你走上使foo
和bar
关闭或接受参数的道路sync.WaitGroup
,每个函数首先将自己添加到组中并在退出之前等待它。那条路就是疯狂。
如果foo
在bar
有机会将自身添加到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
}