自学内容网 自学内容网

go语言中使用WaitGroup和channel实现处理多线程问题

WaitGroup

背景

如果将一个任务分为任意个小任务,并且不关心小任务的执行顺序,并且希望等待全部的小任务执行完成后再去操作后面的逻辑,那我推荐你用sync.WaitGRoup

使用方法

比如,有一个任务需要执行 3 个子任务,那么可以这样写:

package main

import (
"fmt"
"sync"
)

func main() {
// 定义信号量
var wg sync.WaitGroup
// wg 添加任务数量
wg.Add(3)
// 创建三个携程处理wg
go func(i int, wg *sync.WaitGroup) {
// 提前定义结束
defer wg.Done()
fmt.Printf("执行任务%d\n", i)

}(1, &wg)
go func(i int, wg *sync.WaitGroup) {
// 提前定义结束
defer wg.Done()
fmt.Printf("执行任务 %d\n", i)

}(2, &wg)
go func(i int, wg *sync.WaitGroup) {
// 提前定义结束
defer wg.Done()
fmt.Printf("执行任务 %d\n", i)

}(3, &wg)
// 等待所有携程执行完毕
fmt.Println("等待所有任务执行中....")
wg.Wait()
fmt.Println("所有任务执行完了....")
}

踩坑点避免

1.调用时应该调用&wg而不是wg(调用引用)

// 正确
go handlerTask1(&wg)

// 错误
go handlerTask1(wg)

2.确保wg.Add()应该在wg.Wait()之前执行

 // 错误
var wg sync.WaitGroup

go handlerTask1(&wg)

wg.Wait()

...

func handlerTask1(wg *sync.WaitGroup) {
wg.Add(1)
defer wg.Done()
fmt.Println("执行任务 1")
}

3.注意 wg.Add() 和 wg.Done() 的计数器保持一致

小结

sync.WaitGroup 使用起来比较简单,一定要注意不要踩到坑里。

其实 sync.WaitGroup 使用场景比较局限,仅适用于等待全部子任务执行完毕后,再进行下一步处理,如果需求是当第一个子任务执行失败时,通知其他子任务停止运行,这时 sync.WaitGroup 是无法满足的,需要使用到通知机制(channel)。

Channel

由于时间原因,在这里只简单讲一下Channel的作用吧

1.作为锁保证多协程执行时线程安全

2.控制并发数量

https://juejin.cn/post/7175028144812851237


原文地址:https://blog.csdn.net/m0_65431718/article/details/138542019

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!