ホームページ  >  記事  >  バックエンド開発  >  「sync.WaitGroup」とチャネルの組み合わせが Go でデッドロックを引き起こすのはなぜですか?

「sync.WaitGroup」とチャネルの組み合わせが Go でデッドロックを引き起こすのはなぜですか?

Susan Sarandon
Susan Sarandonオリジナル
2024-10-30 17:43:02929ブラウズ

Why Does a `sync.WaitGroup` and Channel Combination Lead to a Deadlock in Go?

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 + "&amp;a=0&amp;b=1&amp;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 サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。