sync.WaitGroup是一种等待n次操作完成的机制。通常,我们使用它来等待n个goroutine完成。下面我们先回顾下开放接口,然后研究一个导致非确定性行为的十分常见的错误。
可以使用sync.WaitGroup的零值创建等待组:
wg := sync.WaitGroup{ }
在内部,sync.WaitGroup拥有一个被默认初始化为0的内部计数器。我们可以使用Add(int)方法增加该计数器,并可以使用Done( )或Add 一个负值来减小它。如果想等待计数器变为0,则必须使用阻塞的Wait( )方法。
注意
计数器不能为负数,否则goroutine会panic。
在下面的示例中,我们将初始化一个等待组,启动三个将自动更新计数器的goroutine,然后等待它们完成。我们希望等待这三个goroutine打印出计数器的值(应该是3)。你能猜出这段代码是否有问题吗?
wg := sync.WaitGroup{}
var v uint64
for i := 0; i < 3; i++ {
go func() { //创建一个goroutine
wg.Add(1) //增加等待组计数器
atomic.AddUint64(&v, 1) //对v进行原子递增
wg.Done()