了解在Go 中使用sync.WaitGroup 和Channel 時的死鎖
開發人員在使用sync.WaitGroup 時經常遇到Go 應用程式永遠不會退出的問題和管道。本文探討了此類死鎖背後的原因,並提供了使用 WaitGroup 的解決方案。
考慮提供的範例程式碼:
package main import ( "fmt" "io" "log" "net/http" "os" "sync" ) var symbols = []string{ "ASSA-B.ST", "ELUX-B.ST", "HM-B.ST", } func main() { fmt.Println("fetching quotes...") fetchedSymbols := make(chan string) var wg sync.WaitGroup wg.Add(len(symbols)) for _, symbol := range symbols { go fetchSymbol(symbol, &wg, fetchedSymbols) } for response := range fetchedSymbols { fmt.Println("fetched " + response) } wg.Wait() fmt.Println("done") } func fetchSymbol(symbol string, wg *sync.WaitGroup, c chan<- string) { defer wg.Done() resp, err := http.Get("http://ichart.yahoo.com/table.csv?s=" + symbol + "&a=0&b=1&c=2000") defer resp.Body.Close() if err != nil { log.Fatal(err) } out, err := os.Create("./stock-quotes/" + symbol + ".csv") defer out.Close() if err != nil { log.Fatal(err) } io.Copy(out, resp.Body) c <- symbol }
在此程式碼中,fetchedSymbols 上的範圍循環將阻塞 main無限期地發揮作用。為什麼?因為 fetchedSymbols 通道永遠不會關閉。為了解決這個死鎖,可以使用WaitGroup 來發出何時關閉通道的信號:
... go func() { wg.Wait() close(fetchedSymbols) }() for response := range fetchedSymbols { fmt.Println("fetched " + response) } ...
由於WaitGroup 已經跟踪所有goroutine 何時完成,因此可以利用它來觸發fetchedSymbols 通道的關閉,確保範圍循環正常終止。
以上是為什麼 `sync.WaitGroup` 和 Channel 組合會導致 Go 中的死鎖?的詳細內容。更多資訊請關注PHP中文網其他相關文章!