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ユースケースに応じて、複数のゴルーチンから同時に、交換Addして呼び出すことができDoneます。Addが の前に発生する限り、Wait安全なはずです。

好奇心から、現在、WaitGroupはミューテックス、2 つの 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 に答える