Rumah >pembangunan bahagian belakang >Golang >Mengapa Gabungan `sync.WaitGroup` dan Saluran Membawa kepada Kebuntuan dalam Pergi?

Mengapa Gabungan `sync.WaitGroup` dan Saluran Membawa kepada Kebuntuan dalam Pergi?

Susan Sarandon
Susan Sarandonasal
2024-10-30 17:43:021005semak imbas

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

Memahami Kebuntuan apabila menggunakan penyegerakan.WaitGroup dan Saluran dalam Go

Pembangun sering menghadapi masalah dengan aplikasi Go mereka yang tidak pernah keluar apabila menggunakan penyegerakan.WaitGroup dan saluran. Artikel ini meneroka sebab di sebalik kebuntuan tersebut dan menawarkan penyelesaian menggunakan WaitGroup.

Pertimbangkan contoh kod yang disediakan:

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
}

Dalam kod ini, gelung julat ke atas fetchedSymbols akan menyekat kod utama berfungsi selama-lamanya. kenapa? Kerana saluran fetchedSymbols tidak pernah ditutup. Untuk menyelesaikan kebuntuan ini, WaitGroup boleh digunakan untuk memberi isyarat bila hendak menutup saluran:

...
go func() {
    wg.Wait()
    close(fetchedSymbols)
}()

for response := range fetchedSymbols {
    fmt.Println("fetched " + response)
}

...

Oleh kerana WaitGroup sudah menjejaki apabila semua goroutine telah selesai, ia boleh dimanfaatkan untuk mencetuskan penutupan saluran fetchedSymbols , memastikan gelung julat ditamatkan dengan anggun.

Atas ialah kandungan terperinci Mengapa Gabungan `sync.WaitGroup` dan Saluran Membawa kepada Kebuntuan dalam Pergi?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn