Go で sync.WaitGroup とチャネルを使用する場合のデッドロックについて
開発者は、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 に対する範囲ループがメイン オブジェクトをブロックします。無限に機能します。なぜ? fetchedSymbols チャネルが閉じられることがないためです。このデッドロックを解決するには、WaitGroup を使用してチャネルを閉じるタイミングを通知できます。
... go func() { wg.Wait() close(fetchedSymbols) }() for response := range fetchedSymbols { fmt.Println("fetched " + response) } ...
WaitGroup はすべてのゴルーチンがいつ完了したかをすでに追跡しているため、これを利用して fetchedSymbols チャネルのクローズをトリガーできます。 、範囲ループが正常に終了するようにします。
以上が「sync.WaitGroup」とチャネルの組み合わせが Go でデッドロックを引き起こすのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。