作成者: ningan123
日付: 2023-03-21 11:05
更新日: 2023-03-21 11:09
説明する
公式ドキュメントにおける WaitGroup の説明は次のとおりです一个 WaitGroup 对象可以等待一组协程结束
。使用方法は次のとおりです。
- メイン コルーチンは、
wg.Add(delta int)
呼び出しによってワーカー コルーチンの数を設定し、ワーカー コルーチンを作成します。 - ワーカー コルーチンが実行された後、それを呼び出す必要があります
wg.Done()
。 - メイン コルーチンは呼び出され、
wg.Wait()
すべてのワーカー コルーチンが実行されてから戻るまでブロックされます。
デモ
問題を説明するために例を挙げてください
次の 3 つの小さなデモは同じ機能を実現できますが、次のデモは前のデモよりも洗練されています。
package main
import (
"fmt"
"sync"
)
// // 方法1
// func main() {
// for i := 0; i < 100; i++ {
// go fmt.Println(i)
// }
// time.Sleep(time.Second)
// }
// // 方法2
// func main() {
// num := 100
// c := make(chan bool, num)
// for i := 0; i < num; i++ {
// go func(i int) {
// fmt.Println(i)
// c <- true
// }(i)
// }
// for i := 0; i < num; i++ {
// <-c
// }
// }
// 方法3
func main() {
wg := sync.WaitGroup{
}
num := 20
wg.Add(num)
for i := 0; i < num; i++ {
go func(i int) {
// wg.Done() // 放这会有问题
fmt.Println(i)
// wg.Done()
}(i)
}
wg.Wait()
}
方法 3 の場合、wg.Done() を書き込み終了後に配置する必要があります。そうしないと問題が発生します。
wg.Done() が位置 1 に配置されている場合、コードを 2 回実行した結果は次のようになります。コルーチンが実行を開始する前にメインプロセスが終了する可能性が高いことがわかります。
############## wg.Done()放在位置1处 ##############
# go run main.go
9
2
0
# go run main.go
9
0
1
2
3
4
5
6
7
8
wg.Done() を位置 2 に配置しても問題はありません。コルーチンの実行後に waitGroup 内のコルーチンが 1 ずつデクリメントされるたびに、効果はありません~