亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

多個 goroutines 和一個通道的死鎖

多個 goroutines 和一個通道的死鎖

Go
梵蒂岡之花 2023-05-22 17:23:49
我有一個我無法解決的死鎖問題。我擁有一些 url,goroutine 中的每個 url 都會給我帶來足夠的數據。我將這些數據放入單個通道中。但是,如果我關閉頻道,程序將無法運行,如果我離開頻道,則會出現打開死鎖。不知道怎么解決,求大神解答下面我把問題簡化一下package mainimport (    "fmt")type urlNumbers struct {    url string    numbers []int}func getNumbers(urls []urlNumbers) chan int {    ch := make(chan int)    for _, url := range urls {        go allNumbersOfURL(url, ch)    }    return ch}func allNumbersOfURL(url urlNumbers, ch chan int) {    for _, i := range url.numbers {        ch <- i    }}func main() {    url1 := urlNumbers {url: "1", numbers: []int{1, 2, 3}}    url2 := urlNumbers {url: "2", numbers: []int{4, 5, 6}}    url3 := urlNumbers {url: "3", numbers: []int{7, 8, 9}}    url4 := urlNumbers {url: "4", numbers: []int{10, 11, 12}}    c := getNumbers([]urlNumbers{url1, url2, url3, url4})    for i := range c {        fmt.Println(i)    }    fmt.Println("END")}輸出go run app.go101112471235689fatal error: all goroutines are asleep - deadlock!
查看完整描述

2 回答

?
楊__羊羊

TA貢獻1943條經驗 獲得超7個贊

您正在使用for i := range c迭代通道,但代碼不知道何時停止。range在通道上等待通道關閉,或永遠掛起。這就是為什么會出現僵局。


在通過頻道發布所有“url”后,您應該關閉您的頻道。這可以在 的幫助下實現sync.WaitGroup。在getNumbers循環之前,您可以使用 aWaitGroup并設置要等待的作業數len(urls):


wg:=&sync.WaitGroup{}

wg.Add(len(urls))

并在返回之前添加一個新的協程ch:


go func() {

    wg.Wait()

    close(ch)

} ()

然后在 中allNumbersOfURL,添加WaitGroup作為新參數,并在循環后設置一個完成的工作。


func allNumbersOfURL(url urlNumbers, ch chan int,wg *sync.WaitGroup) {

    for _, i := range url.numbers {

        ch <- i

    }

    wg.Done()

}

游樂場:https://play.golang.org/p/--7x7eXIzP9


查看完整回答
反對 回復 2023-05-22
?
江戶川亂折騰

TA貢獻1851條經驗 獲得超5個贊

通道必須關閉,你可以用來sync.WaitGroup等待任務完成。這是對功能的修改getNumbers


func getNumbers(urls []urlNumbers) <-chan int {

    ch := make(chan int)


    wg := &sync.WaitGroup{}

    for _, url := range urls {

        wg.Add(1)

        go func(url urlNumbers, ch chan<- int) {

            defer wg.Done()

            allNumbersOfURL(url, ch)

        }(url, ch)

    }


    go func(wg *sync.WaitGroup, ch chan int) {

        wg.Wait()

        close(ch)

    }(wg, ch)


    return ch

}

此外,我建議你在論證傳遞中使用通道方向。


可選的 <- 運算符指定通道方向,發送或接收。如果沒有給出方向,則通道是雙向的。


查看完整回答
反對 回復 2023-05-22
  • 2 回答
  • 0 關注
  • 161 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號