0%

Go语言WaitGroup

知法、懂法、守法、用法,做新时代法治社会好青年。

一、基础

      一般情况下,并发goroutine的结束过程是不可控的,也就是说我们并不知道哪个goroutine什么时候结束。但很多情况下,我们需要知道goroutine是否完成,这需要借助sync包的WaitGroup来实现。WaitGroup,它能够一直等到所有的goroutine执行完成,并且阻塞主线程的执行,直到所有的goroutine执行完成。主要包含三个方法:

  • Add:添加或者减少等待goroutine的数量
  • Done:相当于Add(-1),最好用defer注册一下,避免函数内部出错执行不到
  • Wait:执行阻塞,直到所有的WaitGroup数量变成0

二、使用

  1. 基本用法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import (
"fmt"
"sync"
)

func main() {
var wg sync.WaitGroup
var count int
wg.Add(500)
for i := 1; i <= 500; i++ {
//wg.Add(1)
go func() {
count++
defer wg.Done()
}()
}
wg.Wait()
fmt.Println(count)
}
  1. 传参WaitGroup
    • 一定要传&wg
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main

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

func process(i int, wg *sync.WaitGroup) {
fmt.Println("start goroutine ", i)
time.Sleep(2 * time.Second)
fmt.Printf("end goroutine %d\n", i)
defer wg.Done()
}

func main() {
fmt.Println("main process start")
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go process(i, &wg)
}
wg.Wait()
fmt.Println("main process end")
}
  1. amazing
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package main

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

func worker(wg *sync.WaitGroup, i int) {
time.Sleep(time.Second * 1)
// print immediately
// fmt.Println("worker process done", i)
wg.Done()
// may not print
fmt.Println("worker process done", i)
}

func main() {
var wg sync.WaitGroup
wg.Add(5)
for i := 1; i <= 5; i++ {
// fmt.Println(i)
go worker(&wg, i)
}
wg.Wait()
fmt.Println("main process done")
}

三、参考

  1. 参考一
  2. 参考二