1. 简介

本文将介绍 Go 语言中的 WaitGroup 并发原语,包括 WaitGroup 的基本使用方法、实现原理、使用注意事项以及常见的使用方式。能够更好地理解和应用 WaitGroup 来协调多个 Goroutine 的执行,提高 Go 并发编程的效率和稳定性。

2. 基本使用

2.1 定义

WaitGroup

2.2 使用方式

Add(1)Done
Wait()

2.3 使用例子

sync.WaitGroupwg.Add(1)wg.Done

3.实现原理

3.1 设计初衷

WaitGroup

3.2 基本原理

sync.WaitGroupstate1state2WaitGroup
WaitGroupcountercounter
WaitGroupwaiter
WaitGroupWaitGroupcounterwaiterWaitGroup
WaitGroupstate2runtime_Semacquire()runtime_Semrelease()

3.3 代码实现

3.3.1 Add方法

Add()counterAdd

3.3.2 Done方法实现

Done()Adddeltacounter

3.3.3 Wait方法实现

WaitWaiter

3.4 实现补充

AddDoneWaitWaitGroupWaitGroup
WaitGroup

4.使用注意事项

4.1 Add方法和Done方法需要成对出现

下面是一个Add方法和Done方法没有成对出现的例子,此时Add方法调多了,此时计数器永远大于0,Wait 方法会一直阻塞等待。

wg.Add(2)wg.Done()counterwg.Wait()
counterWaitGrouppanic
AddDoneDoneDonewaitGroup

所以在调用Done方法时,需要保证每次调用都与Add方法的调用一一对应,否则会导致程序出现错误。

4.2 在所有任务都已经添加之后,才调用Wait方法进行等待

WaitGroupWait

代码执行结果如下,等待协程被提前唤醒,执行之后的操作,而子任务在等待协程唤醒后才开始执行:

All goroutines finished
Goroutine 1 started
Goroutine 3 started
Goroutine 2 started
Goroutine 1 finished
Goroutine 2 finished
Goroutine 3 finished

AddAdd
WaitGroupwg.WaitWaitGrou
Wait

5. WaitGroup常见使用场景

WaitGroup
ClusterClientForEachMasterWaitGroupForEachMasterfn
ForEachMasterWaitGroupForEachMaster

总结

本文介绍了 Go 语言中的 WaitGroup 并发原语,它提供了一种简单且强大的机制来协调多个 Goroutine 的执行。我们首先学习了 WaitGroup 的基本使用方法,包括如何创建 WaitGroup、如何向计数器中添加值、如何等待所有 Goroutine 完成以及如何在 Goroutine 中通知 WaitGroup 完成。

接着,我们了解了 WaitGroup 的实现原理,包括计数器和等待计数器的实现。了解了实现原理之后,我们可以更好地理解 WaitGroup 的内部机制以及如何更好地使用它来实现我们的需求。