「Golang」sync.WaitGroup源码讲解

sync.WaitGroup介绍

当我们在开发过程中,经常需要在开启多个goroutine后,等待全部的goroutine执行完毕后才进行下一步的业务逻辑执行。此时我们可能会采用轮询的方式去定时侦测已经开启的多个goroutine的业务是否执行完毕,但是这样性能很低,并且持续占用cpu时间片很消耗cpu的资源,此时我们就该使用sync.WaitGroup来完成此次操作。举个🌰,下列代码是开了10个goroutine后等待其各睡眠5秒之后进行后续操作的sync.WaitGroup方法实现。

func main() {
   
	// 创建对象
	var wait sync.WaitGroup
	for i := 0; i < 10; i++ {
   
		// 为需要等待结束的goroutine数量+1
		wait.Add(1)
		go func() {
   
			time.Sleep(5*time.Second)
			// 结束 使得需要等待的数量-1
			// 等同于  wait.Add(-1)
			wait.Done()
		}()
	}
	// 等待所有执行完毕
	wait.Wait()
	fmt.Println("wait done")
}

上述代码的睡眠5秒可以替换为任何需要在goroutine中执行的业务逻辑,上述代码中出现了下述几个sync.WaitGroup中提供的方法,提供方法很少很简洁,接下来就开始解析一下sync.WaitGroup的相关信息。

func (wg *WaitGroup) Add(delta int) 
func (wg *WaitGroup) Done() 
func (wg *WaitGroup) Wait()

sync.WaitGroup源代码解析

1:sync.WaitGroup结构体的解析

type WaitGroup struct {
   
	// 一个防止sync.WaitGroup被复制的标记结构体
	noCopy noCopy
	// 该数组在32为系统与64位系统中代表的用途不同
	// 首先说64位系统:
	// state1[0]代表当前sync.WaitGroup 调用Add方法增加了多少的couter
	// state1[1]代表调用了Wait方法等待结束的Waiter的数量
	// state1[2]代表Waiter的信号量
	// 其中 state1[0]与state1[1]作者称为计数标记
	// 在32位系统中:
	// state1[0]代表Waiter的信号量
	// state1[1]代表当前sync.WaitGroup 调用Add方法增加了多少的couter
	// state1[2]代表调用了Wait方法等待结束的Waiter的数量
	// 其中 state1[1]与state1[2]作者称为计数标记
	state1 [3]uint32
}

Add(delta int)方法源代码解析

// state 方法用于根据系统是32位还是64位返回对应的state1字段的对应的计数和信号量的地址
func (wg *WaitGroup) state() (statep *uint64, semap *uint32) {
   
	if uintptr(unsafe.Pointer(&wg.state1))%8 == 0 {
   
		// 64位系统返回state1与state1[2],由于数组是连续内存所以可以通过首地址
		
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值