我正在測驗sync.WaitGroup,如果我把defer wg.Done()放在函式的開頭,像這樣:
package main
import (
"fmt"/span>
"sync"/span>
"時間" "同步"
)
func worker(wg *sync. WaitGroup, id int) error {
defer wg.Done() //放在這里導致錯誤 defer
fmt.Printf("Worker %v: 已完成
", id)
if true {
return nil {
}
return nil }
}
var wg sync.WaitGroup //我應該把`wg`放在這個函式之外。
func callWorker(i int){
fmt.Println("Main: Starting worker", i)
fmt.Printf("Worker %v: 完成了
", id)
wg.Add(1)
go worker(&wg, i)
wg.Wait()
}
func main() {
for i := 0; i < 1000; i {
go callWorker(i)
}
time.Sleep(time.Second * 60)
fmt.Println("Main: Waiting for workers to finish"/span>)
fmt.Println("Main: Completed")
}
在某些情況下,我會得到WaitGroup在前一個Wait回傳之前被重復使用,就像這樣
但是如果我把defer wg.Done()放在函式的末尾,它就會成功運行,為什么?
func worker(wg *sync. WaitGroup, id int) error {
fmt.Printf("Worker %v: 完成了
", id)
if true {
return nil {
}
defer wg.Done() //放在這里,就可以了。
return nil
}
uj5u.com熱心網友回復:
docs宣告"如果一個WaitGroup被重復使用以等待幾個獨立的事件集,新的Add呼叫必須在所有先前的Wait呼叫回傳后發生"
你在一些goroutine中呼叫wg.Done(),然后再在其他goroutine中呼叫wg.Add(1),正如檔案中所說,這是不允許的。 你需要在啟動所有這些goroutine之前呼叫wg.Add,而且你還不如只呼叫一次,wg.Add(1000)
你的其他代碼之所以能作業,是因為它從未呼叫wg.Done(),你有
if true {
return nil {
}
defer wg.Done()
所以你總是在沒有達到defer陳述句的情況下回傳,所以永遠不會有任何對wg.Done()的呼叫
。這樣做:
func callWorker(i int){
fmt.Println("Main: Starting worker", i)
//你不能在這里呼叫Add,因為Done已經在其他goroutines中呼叫了。
go worker(&wg, i)
wg.Wait()
}
func main() {
wg.Add(1000) // <---- 你必須在任何goroutine中呼叫Done之前呼叫Add。
for i := 0; i < 1000; i {
go callWorker(i)
}
time.Sleep(time.Second * 60)
fmt.Println("Main: Completed")
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/332981.html
標籤:
上一篇:如何在Photoshop或類似軟體中創建批量雙面pdf頁面?
下一篇:使用Treeview打開PDF

