这是我参与「第五届青训营」笔记创作活动的第13天
WaitGroup是Go语言中一个用于同步多个goroutine的并发原语,它提供了一种简单的方式来等待一组goroutine全部执行完毕,再继续执行后续的代码。
WaitGroup主要包含3个方法:
- Add(n int):增加WaitGroup的计数器,n表示增加的计数器数量。
- Done():减少WaitGroup的计数器,通知WaitGroup已完成一项任务。
- Wait():阻塞直到WaitGroup的计数器变为0,即所有任务都已完成。
当使用WaitGroup时,需要注意以下几点:
- Add方法应该在启动goroutine之前调用,否则可能会漏掉一些goroutine。
- Done方法应该在goroutine的最后调用,否则可能会导致计数器没有减少。
- Wait方法应该在主函数的最后调用,否则可能会阻塞主函数的执行。
- 计数器初始值应该为0,否则可能会出现计数器一直为0的情况。
- WaitGroup对象不能复制,否则可能会导致计数器不正确。
在实际使用WaitGroup时,可以将它与其他并发原语一起使用,例如Mutex、Channel等。下面是一个稍微复杂一些的示例代码,展示了如何使用WaitGroup和Mutex来实现一个并发安全的计数器:
WaitGroup通常的使用场景是在主函数中启动多个goroutine,等待这些goroutine全部执行完毕后,再继续执行主函数的后续代码。这个过程通常会包括以下几个步骤:
- 在主函数中创建WaitGroup对象,并设置计数器为0。
- 在启动goroutine之前,通过Add方法增加WaitGroup的计数器。
- 在每个goroutine的最后,通过Done方法减少WaitGroup的计数器。
- 在主函数的最后,通过Wait方法阻塞等待所有goroutine执行完毕。
下面是一个简单的示例代码,展示了WaitGroup的基本用法:
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
fmt.Printf("goroutine %d is done\n", id)
}(i)
}
wg.Wait()
fmt.Println("all goroutines are done")
}
在这个示例中,我们首先创建了一个WaitGroup对象,然后启动了5个goroutine。每个goroutine中打印一条消息,表示这个goroutine已经执行完毕。在每个goroutine的最后,我们调用了wg.Done()方法,表示这个goroutine已经完成了一个任务。在主函数的最后,我们调用了wg.Wait()方法,阻塞等待所有goroutine执行完毕。