在Go语言的sync包中,提供了基本的同步单元,如互斥锁。除了Once和WaitGroup类型,⼤部分都是适⽤于低⽔平程序线程,高水平的同步使⽤channel通信更好⼀些。 我们可以通过WaitGroup里的wait()方法,来阻塞主线程,直到其他子线程或协程运行完毕,再回到主线程。
type WaitGroup struct { noCopy noCopy state1 [12]byte sema uint32 }
WaitGroup⽤于等待⼀组线程或协程的结束。⽗线程调⽤Add⽅法来设定应等待的线程数量。每个被等待的线程在结束时应调⽤Done⽅法。同时,主线程⾥可以调⽤Wait⽅法阻塞自身,等待Add()方法里声明的线程运行至结束,再返回主线程。
案例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...") }效果如下:
图(1) 阻塞主线程,来运行3个子协程