如何才能等待多个goroutine完成?

如何才能等待多个goroutine完成?,go,goroutine,barrier,Go,Goroutine,Barrier,在我的例子中,如果我们运行go foo()它应该等待bar()完成,反之亦然。最好的方法是什么?请注意,它们也可以独立执行 您可以使用频道!正如我在生锈的围棋中所记得的,这将给出: package main var fooRunning = false var barRunning = false func foo() { fooRunning = true defer func() { fooRunning = false }() if barRunning {

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

您可以使用频道!正如我在生锈的围棋中所记得的,这将给出:

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
    }
    ...
}
func-foo(){
c:=制造(成交量)
围棋(c)

任何具体的设计都不能安全地满足您的需求。按照规定,您说
foo
bar
可以在并发goroutines中运行,如果其中一个或两个都已启动,另一个应该等待它们都完成。不过,这是一个太弱的处方;如果
 foo
启动,然后将完成,但
bar
尚未开始运行?如果
bar
从未运行会怎么样?或者如果
bar
运行,但
foo
从未运行会怎么样

您是否要求
foo
bar
必须启动并完成才能使您的程序正确?如果是这样,我可以猜测您的意思是:您想要一个在继续之前等待它们完成的程序

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

注意,在这里,无论是
foo
还是
bar
都不是相互感知的;为了协调这两个调用,只有它们的调用者是相互感知的

您最初的尝试可能会引导您走上这样一条道路:使
foo
bar
每次关闭或接受一个
sync.WaitGroup
作为参数,在退出之前先执行每个函数。这样做是疯狂的


如果
foo
bar
有机会将自身添加到
WaitGroup
之前启动并完成,则
foo
将在
bar
之前退出,即使您可以声称它们已同时运行,或者与
bar
foo
之前运行相反,可以注册其活动状态,由于这是您的程序中一个不太明确的方面,我建议您将重点放在更高级别的障碍上,而不是放在这两个功能的相互依赖上。

这些要求的相关/可能重复导致大量必须正确处理的竞态条件(如果另一个例程在您的积极检查后立即结束该怎么办?如果其他人在消极检查后立即开始另一个例程该怎么办?等等。如果有人运行两个foo()例程该怎么办?)我强烈建议您创建一个更好的设计,在这种设计中,您没有两个goroutine,它们相互依赖于另一个goroutine的独立运行状态。问题中的代码有一个设计死锁,如@nos所述。没有任何解决方案可以适用于给定的场景。如果bar()不运行?通道将阻止进一步执行,对吗?是的,除非另一个goroutine在通道中推送一个整数,
这只提供单向阻塞,问题需要双向;它不解决问题中设计的死锁;它不必要地使用通道。正是为这种用例而构建的,b但是,在从设计中移除死锁之前,无法提出解决方案。我们应该始终为sync.WaitGroup传递指针。游乐场也提出了相同的建议。谢谢,@SouravPrem。我根据您的建议更新了此处的文本和游乐场链接。
func bar(c chan int) {
    // do stuff here
    c <- 0
}
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.")
}