sync.WaitGroup - 为什么一个例行程序来自.wait()

时间:2016-01-03 11:02:21

标签: go

从下面我得到:
包装蛋糕:草莓蛋糕
包装蛋糕:草莓蛋糕
包装蛋糕:草莓蛋糕
包装蛋糕:草莓蛋糕
我们完成了!
包装蛋糕:草莓蛋糕

我没想到“我们完成了!”是第二个?

package main

import (
    "fmt"
    // "strconv"
    // "time"
    "sync"
)

func makeCakeAndSend(cs chan string, wg *sync.WaitGroup) {
    cakeName := "Strawberry Cake "
    cs <- cakeName
    wg.Done()
}

func receiveCakeAndPack(cs chan string) {
    for s := range cs {
        fmt.Println("Packing received cake: ", s)
    }
}

func main() {
    var wg sync.WaitGroup
    cs := make(chan string)

    wg.Add(5)

    for i := 1; i <= 5; i++ {
        go makeCakeAndSend(cs, &wg)
    }

    // go receiveCakeAndPack(cs)

    go func() {
        for s := range cs {
            fmt.Println("Packing received cake: ", s)
        }
        close(cs)
    }()

    wg.Wait()

    fmt.Println("We are done!")

    var input string
    fmt.Scanln(&input)
}

1 个答案:

答案 0 :(得分:4)

这是完全正常的。 wg.Wait()确保所有goroutine在继续之前完成向通道发送数据,它不会同步“Packing received cake”的打印。

当每个人都完成了向频道发送数据时,频道中有一个项目,对吧?但是Waitgroup已经完成了。

所以你有一个竞争条件,主要的goroutine继续“我们完成”,接收goroutine接收和打印。这是不同步的,您无法保证首先会发生这种情况。