14

调用后可以sync.WaitGroup重复使用吗?Wait()

func worker(who string, in <-chan int, wg *sync.WaitGroup) {
    for i := range in {
        fmt.Println(who, i)
        wg.Done()
    }
}

func main() {
    var wg sync.WaitGroup

    AIn := make(chan int, 1)
    BIn := make(chan int, 1)

    go worker("a:", AIn, &wg)
    go worker("b:", BIn, &wg)

    for i := 0; i < 4; i++ {
        wg.Add(2)
        AIn <- i
        BIn <- i
        wg.Wait()
        fmt.Println("main:", i)
    }
}

这个play.golang.org/p/QLsvA-b4Ae按预期运行,但能保证安全吗?文档没有这么说,但也许我只是偏执。

4

1 回答 1

24

是的,它是安全的。事实上,它甚至比这更安全。您可以Wait同时使用多个 goroutine,并根据您的用例进行交换Add和调用。Done只要Add发生在 之前Wait,您应该是安全的。

只是出于好奇,现在WaitGroup使用互斥锁、两个 int32s 计数器和一个信号量来实现:

type WaitGroup struct {
        m       Mutex
        counter int32
        waiters int32
        sema    *uint32
}

这也是一个有趣的测试:

var wg1, wg2 sync.WaitGroup
wg1.Add(1)
wg1.Done()
wg1.Wait()
fmt.Println(wg1 == wg2) // Prints true

最后,如果您确实发现这种使用有任何问题,请报告,因为这将是一个错误。

于 2013-08-30T02:34:22.430 回答