Golang
主页 > 脚本 > Golang >

Go语言等待组sync.WaitGrou的使用

2024-08-17 | 佚名 | 点击:

Go语言中除了可以使用通道(channel)和互斥锁进行两个并发程序间的同步外,还可以使用等待组进行多个任务的同步,等待组可以保证在并发环境中完成指定数量的任务

在 sync.WaitGroup(等待组)类型中,每个 sync.WaitGroup 值在内部维护着一个计数,此计数的初始默认值为零。

等待组有下面几个方法可用,如下表所示。

方法名 功能
(wg * WaitGroup) Add(delta int) 等待组的计数器 +1
(wg * WaitGroup) Done() 等待组的计数器 -1
(wg * WaitGroup) Wait() 当等待组计数器不等于 0 时阻塞直到变 0。

对于一个可寻址的 sync.WaitGroup 值 wg:

等待组内部拥有一个计数器,计数器的值可以通过方法调用实现计数器的增加和减少。当我们添加了 N 个并发任务进行工作时,就将等待组的计数器值增加 N。每个任务完成时,这个值减 1。同时,在另外一个 goroutine 中等待这个等待组的计数器值为 0 时,表示所有任务已经完成。

下面的代码演示了这一过程:

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

28

29

30

31

32

33

34

package main

import (

    "fmt"

    "net/http"

    "sync"

)

func main() {

    // 声明一个等待组

    var wg sync.WaitGroup

    // 准备一系列的网站地址

    var urls = []string{

        "http://www.github.com/",

        "https://www.qiniu.com/",

        "https://www.golangtc.com/",

    }

    // 遍历这些地址

    for _, url := range urls {

        // 每一个任务开始时, 将等待组增加1

        wg.Add(1)

        // 开启一个并发

        go func(url string) {

            // 使用defer, 表示函数完成时将等待组值减1

            defer wg.Done()

            // 使用http访问提供的地址

            _, err := http.Get(url)

            // 访问完成后, 打印地址和可能发生的错误

            fmt.Println(url, err)

            // 通过参数传递url地址

        }(url)

    }

    // 等待所有的任务完成

    wg.Wait()

    fmt.Println("over")

}

代码说明如下:

例子

同时开三个协程去请求网页, 等三个请求都完成后才继续 Wait 之后的工作

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

var wg sync.WaitGroup

var urls = []string{

   "http://www.golang.org/",

   "http://www.google.com/",

   "http://www.somestupidname.com/",

}

for _, url := range urls {

   // Increment the WaitGroup counter.

   wg.Add(1)

   // Launch a goroutine to fetch the URL.

   go func(url string) {

      // Decrement the counter when the goroutine completes.

      defer wg.Done()

      // Fetch the URL.

      http.Get(url)

   }(url)

}

// Wait for all HTTP fetches to complete.

wg.Wait()

或者下面的代码
用于测试 给chan发送 1千万次,并接受1千万次的性能

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

28

29

30

31

32

33

34

35

36

37

import (

   "fmt"

    "sync"

    "time"

)

 

const (

   num = 10000000

)

 

func main() {

   TestFunc("testchan", TestChan)

}

 

func TestFunc(name string, f func()) {

   st := time.Now().UnixNano()

   f()

   fmt.Printf("task %s cost %d \r\n", name, (time.Now().UnixNano()-st)/int64(time.Millisecond))

}

 

func TestChan() {

   var wg sync.WaitGroup

   c := make(chan string)

   wg.Add(1)

 

   go func() {

      for _ = range c {

      }

      wg.Done()

   }()

 

   for i := 0; i < num; i++ {

      c <- "123"

   }

   close(c)

   wg.Wait()

}

原文链接:
相关文章
最新更新