Contents
8.14. Go语言等待组¶
除了可以使用通道(channel)和互斥锁进行两个并发程序间的同步外,还可以使用等待组进行多个任务的同步。
等待组的方法
方法名 |
功能 |
|---|---|
(wg * WaitGroup) Add(delta int) |
等待组的计数器 +1 |
(wg * WaitGroup) Done() |
等待组的计数器 -1 |
(wg * WaitGroup) Wait() |
当等待组计数器不等于 0 时阻塞直到变 0。 |
等待组内部拥有一个计数器,计数器的值可以通过方法调用实现计数器的增加和减少。 当我们添加了N个并发任务进行工作时,就将等待组的计数器值增加N。 每个任务完成时,这个值减1。同时,在另外一个goroutine中等待这个等待组的计数器值为0时,表示所有任务已经完成。
package main
import (
"fmt"
"net/http"
"sync"
)
func main() {
// 声明一个等待组
var wg sync.WaitGroup
// 准备一系列的网站地址
var urls = []string{
"http://www.github.com/",
"https://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")
}
/*
https://qiniu.com/ <nil>
http://www.github.com/ <nil>
https://www.golangtc.com/ Get https://www.golangtc.com/: net/http: TLS handshake timeout
over
*/
等待一组Goroutine返回
package main
import (
"sync"
"fmt"
"time"
)
func calc(w *sync.WaitGroup, i int) {
fmt.Println("calc: ", i)
time.Sleep(time.Second)
w.Done()
}
func main() {
wg := sync.WaitGroup{}
for i:=0; i<10; i++ {
wg.Add(1)
go calc(&wg, i)
}
wg.Wait()
fmt.Println("all goroutine finish")
}