如何等待多个goroutine完成?

时间:2017-09-15 08:30:29

标签: go goroutine barrier

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()完成,反之亦然。最好的方法是什么?请注意,它们也可以独立执行。

2 个答案:

答案 0 :(得分:0)

任何具体设计都无法安全地满足您的要求。按照规定,你说foobar 可以在并发goroutine中运行,如果其中一个或两个都已启动,另一个应该等待它们两个完成。但是,处方太弱了;如果foo开始然后结束会发生什么,但bar尚未开始运行?如果bar根本没有运行怎么办?或者如果bar运行,但foo从未执行过,该怎么办?

您是否要求foobar必须启动并完成以使您的计划正确无误?如果是这样,我可以猜测你的意思是什么:你想要一个等待它们的barrier在继续之前完成。

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.")
}

That same example in the Playground

请注意,此处foobar都不会相互了解;只有他们的呼叫者才能协调这两个电话。

您的原始尝试可能会引导您将foobar各自关闭或接受sync.WaitGroup作为参数,每个函数首先adding itself to the group并且退出前waiting on it。那种方式就是疯狂。

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

答案 1 :(得分:-1)

您可以使用频道!正如我记得生锈的那样,这会给出:

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

并在栏中

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