golang語言非同步通訊之WaitGroup
golang語言非同步通訊之WaitGroup
簡介
WaitGroup的用途是使得主執行緒一直阻塞等待直到所有相關的子goroutine都已經完成了任務。
sync.WaitGroup只有3個API
- Add() # 新增計數
- Done() # 減掉計數,等價於Add(-1),這樣sync.WaitGroup只有兩個API了
- Wait() # 阻塞直到計數為零
用法例子1:正常用法
var wg sync.WaitGroup
func foo1() {
log.Println("entry foo1")
time.Sleep(5 * time.Second)
wg.Done()
log.Println("exit foo1")
}
func foo2() {
log.Println("entry foo2")
time.Sleep(2 * time.Second)
wg.Done()
log.Println("exit foo2")
}
func main() {
log.Println("entry main")
wg.Add(1)
go foo1()
wg.Add(1)
go foo2()
log.Println("wg.Wait()")
wg.Wait()
log.Println("exit main")
}
主執行緒呼叫起兩個子執行緒foo1和foo2並且等待他們的完成。
執行結果
2018/02/07 14:29:21 entry main
2018/02/07 14:29:21 wg.Wait()
2018/02/07 14:29:21 entry foo1
2018/02/07 14:29:21 entry foo2
2018/02/07 14:29:23 exit foo2
2018/02/07 14:29:26 exit foo1
2018/02/07 14:29:26 exit main
用法例子2:Done()過多
func main() {
log.Println("entry main")
var wg sync.WaitGroup
wg.Done()
log.Println("exit main")
}
在這個例子中,我們一上來就Done
$ go build && ./main
2018/02/07 14:33:59 entry main
panic: sync: negative WaitGroup counter
goroutine 1 [running]:
sync.(*WaitGroup).Add(0xc42006c060, 0xffffffffffffffff)
/usr/local/go/src/sync/waitgroup.go:75 +0x134
sync.(*WaitGroup).Done(0xc42006c060)
/usr/local/go/src/sync/waitgroup.go:100 +0x34
main.main()
/path_to/main.go:30 +0x89
計數器小於零,panic
用法例子3:Done()過少
var wg sync.WaitGroup
func foo1() {
log.Println("entry foo1")
time.Sleep(5 * time.Second)
//wg.Done()
log.Println("exit foo1")
}
func foo2() {
log.Println("entry foo2")
time.Sleep(2 * time.Second)
//wg.Done()
log.Println("exit foo2")
}
func main() {
log.Println("entry main")
wg.Add(1)
go foo1()
wg.Add(1)
go foo2()
log.Println("wg.Wait()")
wg.Wait()
log.Println("exit main")
}
這個例子中我們註釋掉了兩個子執行緒中的Done()函式,執行結果:
$ go build && ./wg
2018/02/07 14:36:03 entry main
2018/02/07 14:36:03 wg.Wait()
2018/02/07 14:36:03 entry foo2
2018/02/07 14:36:03 entry foo1
2018/02/07 14:36:05 exit foo2
2018/02/07 14:36:08 exit foo1
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [semacquire]:
sync.runtime_Semacquire(0x55ad7c)
/usr/local/go/src/runtime/sema.go:56 +0x39
sync.(*WaitGroup).Wait(0x55ad70)
/usr/local/go/src/sync/waitgroup.go:131 +0x72
main.main()
/path_to/main.go:36 +0x127
這個錯誤表明,在最後一個活動執行緒foo1退出的時候,go檢測到當前沒有還在執行的執行緒,而還有在等待的執行緒,所以必然發生了死鎖現象,這是go的一種自我保護機制。
相關文章
- Go語言 | 併發設計中的同步鎖與waitgroup用法GoAI
- 同步通訊和非同步通訊非同步
- golang(gin框架),基於RESTFUL的跨語言遠端通訊嘗試Golang框架REST
- Golang WaitGroup原始碼分析GolangAI原始碼
- C語言實現TCP通訊C語言TCP
- Go語言實現TCP通訊GoTCP
- 跨語言通訊方案比較
- 同步、非同步通訊非同步
- IO通訊模型(二)同步非阻塞模式NIO(NonBlocking IO)模型模式BloC
- Golang試用阿里通義千問大語言模型Golang阿里模型
- RabbitMQ 入門(一)同步通訊和非同步通訊MQ非同步
- Dart 語言非同步之Stream詳解Dart非同步
- golang開發:CSP-WaitGroup MutexGolangAIMutex
- Golang Sync.WaitGroup 使用及原理GolangAI
- 【Golang 基礎系列十】Go 語言 條件語句之ifGolang
- golang語言除錯Golang除錯
- 3.Vue非父子元件之間的通訊Vue元件
- Android跨程式通訊之非AIDL(二)AndroidAI
- 通訊錄的c語言程式編輯C語言
- 年度語言 golang 使用感受Golang
- 瀏覽器與go語言的websocket通訊瀏覽器GoWeb
- Golang通脈之反射Golang反射
- Golang通脈之方法Golang
- 同步協程的必備工具: WaitGroupAI
- golang實現子程式通訊Golang
- Go語言實現的簡易TCP通訊框架GoTCP框架
- 語言是 Go 還是 Golang?Golang
- golang 利用 WaitGroup 控制多個 goroutine 同時完成GolangAI
- Golang WaitGroup 底層原理及原始碼詳解GolangAI原始碼
- 關於應用整合:同步與非同步通訊模式之間的比較非同步模式
- golang 封裝 rabbitmq,正常訊息,延時訊息,非炫技,僅記錄(golang新人)Golang封裝MQ
- Storm入門之第7章使用非JVM語言開發ORMJVM
- Golang語言排序的幾種方式Golang排序
- mac下golang語言配置goproxyMacGolang
- 網路IO之阻塞、非阻塞、同步、非同步總結非同步
- vue2.0 非父子元件之間的單一事件通訊Vue元件事件
- Golang通脈之併發初探Golang
- C語言 非同步回撥C語言非同步