理解WaitGroup
WaitGroup,同步等待组。 在类型上,它是一个结构体。一个WaitGroup的用途是等待一个goroutine的集合执行完成。主goroutine调用了Add()方法来设置要等待的goroutine的数量。然后,每个goroutine都会执行并且执行完成后调用Done()这个方法。与此同时,可以使用Wait()方法来阻塞,直到所有的goroutine都执行完成。
开看看几个重要的方法
package main
import "sync"
var g sync.WaitGroup
func main() {
// Add这个方法,用来设置到WaitGroup的计数器的值。我们可以理解为每个waitgroup中都有一个计数器
// 用来表示这个同步等待组中要执行的goroutin的数量。
// 如果计数器的数值变为0,那么就表示等待时被阻塞的goroutine都被释放,如果计数器的数值为负数,那么就会引发恐慌,程序就报错了。
g.Add(1)
// 就是当WaitGroup同步等待组中的某个goroutine执行完毕后,设置这个WaitGroup的counter数值减1
g.Done()
// 表示让当前的goroutine等待,进入阻塞状态。一直到WaitGroup的计数器为零。才能解除阻塞,这个goroutine才能继续执行
g.Wait()
}
// Done() 源码
func (wg *WaitGroup) Done() {
// 就是操作 Add(-1)
wg.Add(-1)
}
上代码
package main
import (
"fmt"
"sync"
)
var g sync.WaitGroup
func main() {
// 定义等待组,要执行的 goroutine 为 2
g.Add(2)
// 执行 goroutine
go fun1()
go fun2()
// main 进入阻塞状态,等待 g 当中的 goroutine 执行完
fmt.Println("我是主 goroutine ,我刷点存在感。。。")
// 进入等待
g.Wait()
// 解除阻塞
fmt.Println("我还是主 goroutine,我再来点存在感,拜拜。。。")
}
func fun1() {
// 执行
fmt.Println("我是fun1,我在工作。。。")
// 等待组 -1
g.Done()
// 结束执行
fmt.Println("我是fun1。。。我完事了")
}
func fun2() {
// 执行
fmt.Println("我是fun2,我在工作。。")
// 等待组 -1
g.Done()
// 结束执行
fmt.Println("我是fun2。。。我完事了")
}
执行结果
我是fun1,我在工作。。。
我是fun1。。。我完事了
我是主 goroutine ,我刷点存在感。。。
我是fun2,我在工作。。
我是fun2。。。我完事了
我还是主 goroutine,我再来点存在感,拜拜。。。