GO——waitgroup

参考:https://studygolang.com/articles/12972

背景

父协程需要等待子协程完成

  • https://blog.csdn.net/cdq1358016946/article/details/106380790
    • 当父协程不是main时,其退出不会影响子协程
    • main退出时,所有的协程都会退出

举例

  • 一个业务并行从不同数据源(如redis、mysql、es)取数,然后整合,需要等待所有取数动作都完成再返回
package main

import (
	"fmt"
	"time"
)

func main() {
	for i:=0;i<100;i++{
		go func(i int) {
			fmt.Println(i)
		}(i)
	}
	time.Sleep(time.Second)
}
  • time.sleep的参数单位时纳秒
解决方案
  • 父协程sleep一段时间
    • 不靠谱,因为大多数情况下
  • 使用channel
    • 大材小用
    • 当协程多的时候,channel消耗内存也多
  • sync.WaitGroup
func main() {
    c := make(chan bool, 100)
    for i := 0; i < 100; i++ {
        go func(i int) {
            fmt.Println(i)
            c <- true
        }(i)
    }

    for i := 0; i < 100; i++ {
        <-c
    }
}
WatiGroup
  • 等待组
  • 三个方法
    • ADD(delta int)
      • 计数器加delta
      • 内部实现时,在count变成0时,会发出信号量告诉waiter所有任务已完成
        • 信号量?
          • 参考:https://zhuanlan.zhihu.com/p/337290029
    • Done()
      • 计数器减1
      • 内部调用的Add()方法实现的计数器减一操作
    • Wait()
      • 计数器不等于零时,阻塞
        • 看源码,像是循环查询,判断
        • 参考:https://segmentfault.com/a/1190000039192995
使用

一等多

package main

import (
	"fmt"
	"sync"
)

func main() {
	wg := sync.WaitGroup{}
	wg.Add(100)
	for i:=0;i<100;i++{
		go func(i int) {
			fmt.Println(i)
			wg.Done()
		}(i)
	}
	wg.Wait()
}

多等一

package main

import (
	"fmt"
	"sync"
	"time"
)

func main() {
	wg := sync.WaitGroup{}
	wgMutiPass := sync.WaitGroup{}
	wg.Add(1)
	wgMutiPass.Add(100)
	for i:=0;i<100;i++{
		go func(i int) {
			wg.Wait()
			fmt.Println(i)
			wgMutiPass.Done()
		}(i)
	}
	fmt.Println("开始等待")
	time.Sleep(time.Second * 3)
	fmt.Println("结束等待")
	wg.Done()

	wgMutiPass.Wait()
}

你可能感兴趣的:(golang,后端,并发)