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
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!
