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)!