Go言語の同期パッケージには、ミューテックスロックなどの基本的な同期ユニットが用意されています。OnceタイプとWaitGroupタイプを除いて、それらのほとんどは低レベルのプログラムスレッドに適しており、高レベルの同期にはチャネル通信を使用することをお勧めします。
WaitGroupのwait()メソッドを使用して、他の子スレッドまたは列が実行を終了するまでメインスレッドをブロックしてから、メインスレッドに戻ることができます。
WaitGroup同期待機グループ
タイプWaitGroupstruct { noCopy noCopy state1 [12] byte sema uint32 }
WaitGroupは、スレッドまたは列のグループの終了を待機するために使用されます。スレッドはAddメソッドを呼び出して、待機するスレッドの数を設定します。待機中の各スレッドは、最後にDoneメソッドを呼び出す必要があります。同時に、メインスレッドはWaitメソッドを呼び出してそれ自体をブロックし、Add()メソッドで宣言されたスレッドが最後まで実行されるのを待ってから、メインスレッドに戻ることができます。
WaitGroupのメソッド
- func(wg * WaitGroup)Add(delta int)
Addメソッドは、内部カウントにデルタを追加します。デルタは負の数にすることができます。内部カウンターが0になると、Waitメソッドによってブロックされているすべてのスレッドが解放されます。カウンターが0未満の場合、メソッドパニック。Addと正の数の呼び出しは、Waitの前に使用する必要があることに注意してください。そうしないと、Waitは数スレッドしか待機しない場合があります。一般に、Add()メソッドは、待機する必要のある新しいスレッドまたはその他のイベントを作成する前に呼び出す必要があります。 - func(wg * WaitGroup)Done()
Doneメソッドは、WaitGroupカウンターの値を減らすため、スレッドの最後で実行する必要があります。 - func(wg * WaitGroup)Wait()
Waitメソッドは、WaitGroupカウンターが0に減少するまでブロックします。
ケース1.WaitGroupは、wait()を使用して、メイン関数をブロックし、3つのサブコルーチンを実行します。
//myWaitGroupDes.go
// myWatiGroupDes project main.go
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
func printNumA(wg *sync.WaitGroup) {
k := 0
for i := 11; i <= 20; i += 2 {
fmt.Printf("子协程A[%d]= %d \n", k, i)
time.Sleep(time.Duration(rand.Intn(1000)))
k++
}
wg.Done() //计算器减1
}
func printNumB(wg *sync.WaitGroup) {
k := 0
for i := 22; i <= 30; i += 2 {
fmt.Printf("子协程B[%d]= %d \n", k, i)
time.Sleep(time.Duration(rand.Intn(1000)))
k++
}
wg.Done() //计算器减1
}
func printNumC(wg *sync.WaitGroup) {
k := 0
for i := 'a'; i <= 'e'; i++ {
fmt.Printf("子协程C[%d]= %c \n", k, i)
time.Sleep(time.Duration(rand.Intn(1000)))
k++
}
wg.Done() //计算器减1
}
func main() {
var wg sync.WaitGroup
fmt.Printf("%T\n", wg)
fmt.Println(wg)
wg.Add(3)
rand.Seed(time.Now().UnixNano())
go printNumA(&wg)
go printNumB(&wg)
go printNumC(&wg)
wg.Wait()
fmt.Println("main解除阻塞,main is over...")
}
効果は次のとおりです。