乐趣区

关于golang:Go-sync包的WaitGroup同步等待组详解

    sync 全称是 synchronization,意思是同步。
WaitGroup 同步期待组是有一组 goroutine 要期待执行,而以后的 goroutine 须要期待这一组 goroutine 都执行完能力执行。
    上面是 WaitGroup 的定义:

type WaitGroup struct {//}

    每个 WaitGroup 中都有一个计数器 counter 记录要期待执行 gorouting 的数量,能够通过 Add 这个办法来设置同步期待组中期待 goroutine 的个数。每个 goroutine 都会执行,执行完之后都会调用 done 办法示意把计数器的值 -1,与此同时,应用 wait 办法阻塞,直到所 goroutine 都执行结束。
func (wg *WaitGroup) Add(delta int)

  • 如果计数器的值为 0,那么期待过程中被阻塞的 goroutine 都会被开释
  • 如果计数器得悉为负,那么就会引发 panic

那么具体什么状况下用,怎么应用呢?
上面举个例子:

package main

import "fmt"

func main() {
    //waitGroup
    go fun1()
    go fun2()}

func fun1() {
    for i := 1; i < 10; i++ {fmt.Println("print A in fun1", i)
    }
}

func fun2() {
    for i := 0; i < 10; i++ {fmt.Println("\t fun2 print:", i)
    }
}

这样最初什么都没有打印,因为主 goroutine 在 fun1 fun2 这两个 goroutine 执行之前完结了。这时候就能够用 WaitGroup 了。

package main

import (
    "fmt"
    "sync"
)

// 创立同步期待组
var wg sync.WaitGroup

func main() {
    //waitGroup
    wg.Add(2) // 设置计数器为 2(goroutine 的个数)go fun1()
    go fun2()
    fmt.Println("main 进入阻塞状态,须要期待 wg 的 goroutine 完结")
    wg.Wait() // 示意 main goroutine 进入阻塞
    fmt.Println("计数器归零 进行阻塞")
}

func fun1() {defer wg.Done() // 计数器 -1
    for i := 1; i < 10; i++ {fmt.Println("print A in fun1", i)
    }
}

func fun2() {defer wg.Done() // 计数器 -1
    for i := 0; i < 10; i++ {fmt.Println("\t fun2 print:", i)
    }
}

后果如下:

main 进入阻塞状态,须要期待 wg 的 goroutine 完结
print A in fun1 1
print A in fun1 2
         fun2 print:  0
         fun2 print:  1
         fun2 print:  2
         fun2 print:  3
         fun2 print:  4
print A in fun1 3
print A in fun1 4
print A in fun1 5
print A in fun1 6
print A in fun1 7
print A in fun1 8
print A in fun1 9
         fun2 print:  5
         fun2 print:  6
         fun2 print:  7
         fun2 print:  8
         fun2 print:  9
计数器归零 进行阻塞 

后果第一行,阐明两个 goroutine 曾经都启动了,而后交替应用 CPU 的工夫片。
另外 如果函数执行结束的时候,计数器的值依然大于 0,会引起 deadlock。


另外 Go 语言并不举荐上述写法,更加举荐应用 chanel。

材料参考:bilibili

退出移动版