Avito是一名校車司機,他幫助4個Gopher孩子上學。每天,Avito在他們的社區等待孩子們。他不知道孩子們需要多長時間,但他確切地知道有4個孩子他需要等待。
1*aZnEggopv4Tsbyyj3e5JFg.png
當一個孩子準備好時,他/她會說:Done(),將計數器減1。Avito仍然被阻塞,因為計數器仍然大于0。他必須等到所有其他孩子準備好。
1*qouGWmMAqY2CDrzz5widhQ.png
如果有兩個孩子同時準備好,它們的同時準備會導致WaitGroup出現不一致嗎?絕對不會。與sync包中的大多數其他組件一樣,WaitGroup具有內置的同步機制,以處理并發。因此,計數器減少了準備好的孩子數量。
1*057bX4zo_LCzEkdzGyDYpA.png
在最后一個孩子準備好后,Avito啟動引擎,將他們送到學校。
1*rjH8OR3t7QgUx-dO-Iszeg.png
就是這樣!正如我所說,sync.WaitGroup很簡單。
如果一個孩子花費太多時間準備,他們會不會因此遲到?如果Avito在時間到達時不管怎樣都開始行駛會更好嗎?嗯,Golang傾向于保持一切盡可能簡潔,因此與其他編程語言中的CountDownLatch(例如Java中的)不同,sync.WaitGroup默認情況下不支持超時。在這種情況下,選擇語句可能會有所幫助。
func main() { wg := sync.WaitGroup{} wg.Add(1) go func() { defer wg.Done() time.Sleep(5 * time.Second) }() done := make(chan bool) go func() { wg.Wait() close(done) }() select { case <-done: log.Println("All done") case <-time.After(1 * time.Second): log.Println("Hit timeout") }}
在上面的示例中,Avito(主Goroutine)等待孩子(子Goroutines)。當我們希望子Goroutines等待主Goroutine時,WaitGroup也可以使用。想象一下孩子們正在進行體育課。Torcher - 體育老師,在學生中主持比賽。他向WaitGroup中Add(1),并要求所有孩子在相同的WaitGroup上Wait()。
1*btDQK4QKsu1HkEpfJDa2EA.png
當Torcher調用wg.Done()時,計數器變為0,允許所有孩子同時開始奔跑。
1*VkV3VlRTx5jxXhauBH0_Dg.png
package mainimport ( "log" "sync" "time")func main() { kids := []string{"Partier", "Stringer", "Candier", "Swimmer"} wg := sync.WaitGroup{} wg.Add(len(kids)) for _, kid := range kids { go func(name string) { defer wg.Done() prepare(name) }(kid) } log.Printf("Avito: I'm waiting for %d kids/n", len(kids)) wg.Wait() log.Println("Avito: The kids are all ready, go!")}func prepare(name string) { log.Printf("%v: I'm preparing for school/n", name) time.Sleep(2 * time.Second) log.Printf("%v: I'm ready/n", name)}
本文鏈接:http://www.tebozhan.com/showinfo-26-14622-0.htmlGo并發可視化解釋:sync.WaitGroup
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com