2.4 WaitGroup
在并发编程中,我们经常需要等待一组 goroutine 完成后再继续执行下一步操作。Go 语言提供了 sync.WaitGroup 来实现这种需求,它允许我们通过计数器机制来等待一组 goroutine 完成执行。下面我们详细介绍 WaitGroup 的概念、使用方法及示例。
2.4.1 什么是WaitGroup
WaitGroup 是 Go 标准库 sync 包中的一种同步原语,用于等待一组 goroutine 完成执行。WaitGroup 通过一个计数器来跟踪 goroutine 的执行状态,当所有 goroutine 完成时,WaitGroup 允许程序继续执行。
WaitGroup 主要有三个方法:
Add:增加计数器的值,参数为正数。Done:减少计数器的值,相当于Add(-1)。Wait:阻塞,直到计数器的值变为零。
2.4.2 WaitGroup的使用方法
使用 WaitGroup 非常简单。首先,创建一个 WaitGroup 实例。在需要等待的每个 goroutine 启动前调用 Add 方法增加计数器的值,在每个 goroutine 完成时调用 Done 方法减少计数器的值,最后在主 goroutine 中调用 Wait 方法等待所有 goroutine 完成。以下是基本使用示例:
package main
import (
"fmt"
"sync"
"time"
)
func worker(id int, wg *sync.WaitGroup) {
defer wg.Done()
fmt.Printf("Worker %d starting\n", id)
time.Sleep(time.Second)
fmt.Printf("Worker %d done\n", id)
}
func main() {
var wg sync.WaitGroup
for i := 1; i <= 5; i++ {
wg.Add(1)
go worker(i, &wg)
}
wg.Wait()
fmt.Println("All workers completed")
}
在这个例子中,我们启动了五个 goroutine,每个 goroutine 都在完成后调用 wg.Done()。主 goroutine 使用 wg.Wait() 等待所有 goroutine 完成。
2.4.3 WaitGroup的应用场景
WaitGroup 适用于以下场景:
- 并行任务等待:等待一组并行执行的任务完成后再继续执行后续操作。
- 批处理任务:在批处理任务中,启动多个 goroutine 并行处理任务,等待所有任务完成后汇总结果。
- 测试用例:在并发测试用例中,使用 WaitGroup 等待所有测试 goroutine 完成后检查测试结果。
2.4.4 示例代码
以下是一个使用 WaitGroup 实现并行计算平方值的示例:
package main
import (
"fmt"
"sync"
)
func calculateSquare(wg *sync.WaitGroup, num int, results chan<- int) {
defer wg.Done()
square := num * num
results <- square
}
func main() {
var wg sync.WaitGroup
numbers := []int{2, 4, 6, 8, 10}
results := make(chan int, len(numbers))
for _, num := range numbers {
wg.Add(1)
go calculateSquare(&wg, num, results)
}
wg.Wait()
close(results)
for result := range results {
fmt.Println("Square:", result)
}
}
在这个示例中,我们启动多个 goroutine 并行计算平方值,并使用 WaitGroup 等待所有计算完成后,收集并打印结果。
结论
WaitGroup 是 Go 语言中用于等待一组 goroutine 完成的强大工具,通过简单的计数器机制,可以有效地协调多个 goroutine 的执行。在实际应用中,合理使用 WaitGroup 可以简化并发程序的设计,提高代码的可读性和维护性。在接下来的章节中,我们将继续探讨其他同步原语和并发编程技巧,帮助您更好地掌握 Go 的并发编程。