go语言WaitGroup中使用协程嵌套示例代码

2023-06-01 00:00:00 语言 示例 嵌套

WaitGroup是一个计数信号量,可以用来记录并维护运行的goroutine,

它是用来阻塞主协程,可以等待所有协程执行完。


示例代码:

WaitGroup里面在嵌套WaitGroup

func TestGoRoutine(t *testing.T) {

    wg := sync.WaitGroup{}
    limitNum := 3
    wg.Add(limitNum)
   
    for j := 0; j < limitNum; j++ {
        go func(index int) {
       
            defer wg.Done()
            testRoutine(index)
           
        }(j)
    }
   
    wg.Wait()
}

func testRoutine(index int) {
  wg2 := sync.WaitGroup{}
  limitNum2 := 3
  wg2.Add(limitNum2)
 
  for i := 0; i < limitNum2; i++ {
     go func(index2 int) {
    
         defer wg2.Done()
         fmt.Printf("测试上级Index[%d]Index2:[%d] \n", index, index2)
        
    }(i)
 
 } 
     wg2.Wait()
}

打印测试结果:

测试上级Index[2]Index2:[2] 
测试上级Index[2]Index2:[1] 
测试上级Index[1]Index2:[2] 
测试上级Index[1]Index2:[0] 
测试上级Index[1]Index2:[1] 
测试上级Index[2]Index2:[0] 
测试上级Index[0]Index2:[1] 
测试上级Index[0]Index2:[2] 
测试上级Index[0]Index2:[0] 
--- PASS: TestGoRoutine (0.00s)
PASS
进程完成,并显示退出代码 0

相关知识

go协程是平行的,是忽略上下级关系的


原理:

1.waitgroup结构体中state1的格式很重要。共占12个字节。因为64位原子操作需要64位对齐,但32位编译器无法确保它。

所以分配12个字节,然后使用其中的对齐8个字节作为状态数,另外4个作为存储sema;

2.调用Add时,操作高位的计数器值进行加减;

3.调用wait时,低32位的wait数会累加,如果获取到释放的信号后且计数器是0,则调用原语递减信号量的值 结束阻塞。


相关文章