Golang:如何優雅的讓所有子協程執行完後再執行主協程
方法一:channel 實現同步
使用 channel 來完成同步功能。
/*
@Time : 2019-10-28 下午 5:30
@Author : Gerald
@File : 用channel來實現同步
@Software: GoLand
*/
package main
import (
"fmt"
)
func printString(str string) {
for _, data := range str {
fmt.Printf("%c", data)
}
fmt.Printf("\n")
}
var ch = make(chan int)
var tongBu = make(chan int)
func person1() {
printString("Gerald")
tongBu <- 1
ch <- 1
}
func person2() {
<- tongBu
printString("Seligman")
ch <- 2
}
func main() {
// 目的:使用 channel 來實現 person1 先於 person2 執行
go person1()
go person2()
count := 2
// 判斷所有協程是否退出
for range ch {
count--
if 0 == count {
close(ch)
}
}
}
- count 表示有所少個協程
- ch 用來子協程與主協程之間的同步
- tongBu 用來兩個協程之間的同步
- 主協程阻塞等待數據,每當一個子協程執行完後,就會往 ch 裏面寫一個數據,主協程收到後會使 count–,當 count 減爲 0,關閉 ch,主協程將不阻塞在 range ch。
方法二:sync.WaitGroup
Go 語言提供一個更簡單的方式就是,sync.WaitGroup 來實現等待。
sync.WaitGroup 內部是實現了一個計數器,它有三個方法
- Add() 用來設置一個計數
- Done() 用來在操作結束時調用,使計數減1
- Wait() 用來等待所有的操作結束,即計數變爲0。
/*
@Time : 2019-10-28 下午 5:30
@Author : Gerald
@File : 用channel來實現同步
@Software: GoLand
*/
package main
import (
"fmt"
"sync"
)
func printString(str string) {
for _, data := range str {
fmt.Printf("%c", data)
}
fmt.Printf("\n")
}
// 使用 sync.WaitGroup 的方式來實現主協程等待其他子協程
var wg sync.WaitGroup
var tongBu = make(chan int)
func person1() {
printString("Gerald")
tongBu <- 1
wg.Done()
}
func person2() {
<- tongBu
printString("Seligman")
wg.Done()
}
func main() {
wg.Add(2)
// 目的:使用 channel 來實現 person1 先於 person2 執行
go person1()
go person2()
defer close(tongBu)
wg.Wait()
}