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
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。