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

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

為什么這段 Golang 代碼會產生死鎖?

為什么這段 Golang 代碼會產生死鎖?

Go
慕絲7291255 2022-10-10 16:08:48
我是 Golang 的新手,我很難弄清楚為什么下面的代碼會產生死鎖。另外,我該如何修復它才能正常工作?    package main        import "fmt"        func main() {        m := make(map[int]chan string)        go func() {            m[0] = make(chan string)            m[0] <- "abab"        }()        fmt.Println(<-m[0])    }編輯:感謝您的回答!m[0]不幸的是,初始化m[0] = make(chan string)在啟動一個新的 goroutine 之前并不是我想要的。我的問題是:有沒有辦法“動態”創建頻道?例如,我有一個m類型的地圖,map[int]chan string我收到包含類似id類型的請求int。我想通過 channel 發送消息map[id],但是為每個通道初始化通道int成本太高。我該如何解決/解決這個問題?因此,換句話說,我想為每個隊列創建一個單獨的作業隊列,id并懶惰地初始化每個隊列。
查看完整描述

2 回答

?
叮當貓咪

TA貢獻1776條經驗 獲得超12個贊

OP更新問題后更新答案


您可以只循環地圖中的所有鍵,也許還有另一個 goroutine 不斷循環所有鍵。顯然,如果一個鍵沒有被初始化,那么它就不會出現在 for range 循環中。對于每個鍵,您可以啟動一個監聽的 goroutine,這樣它就不會阻塞,或者您可以使用緩沖通道,這樣它們就不會阻塞到緩沖區限制。您也可以最好使用 waitGroup,而不是 time.Sleep(),這些僅用于這個簡單的示例。


package main


import (

"fmt"

    "time"

)

func main() {

    m := make(map[int]chan string)


    go func() {

        m[0] = make(chan string)

        m[0] <- "abab"

    }()


    time.Sleep(time.Second * 1)  //sleep so the above goroutine initializes the key 0 channel


    for key := range m{      //loop on all non-nil keys

        fmt.Println(key)

        go func(k int){        // goroutine to listen on this channel

            fmt.Println(<- m[k])

        }(key)

    }

    time.Sleep(time.Second * 1) //sleep so u can see the effects of the channel recievers



}

  

舊答案


流量就是這樣。主 goroutine 啟動。地圖已創建。主 goroutine 遇到另一個 goroutine。它產生了 goroutine 并繼續它的生活。然后遇到這條線,fmt.Println(<-m[0]),這是一個問題,因為地圖確實初始化了,但是地圖本身的通道沒有初始化!當主 goroutine 到達fmt.Println(<-m[0])時,另一個 goroutine 還沒有初始化通道!所以這是一個簡單的修復,只需在生成 goroutine 之前初始化通道,你就可以開始了!


package main


import "fmt"


func main() {

    m := make(map[int]chan string)

    m[0] = make(chan string)


    go func() {

        m[0] <- "abab"

    }()

    fmt.Println(<-m[0])

}

編輯:請注意這fmt.Println(<-m[0])是阻塞的,這意味著如果在另一個 goroutine 中,您不在通道上發送,您也會陷入死鎖,因為您試圖在沒有人實際發送的情況下在通道上接收。


查看完整回答
反對 回復 2022-10-10
?
慕村225694

TA貢獻1880條經驗 獲得超4個贊

您需要同步通道的創建。

就目前而言,您的主線程到達時<-m[0]仍然m[0]是一個未初始化的通道,并且在未初始化的通道上接收永遠阻塞。

您的 go 例程創建了一個新通道并將其放入m[0],但主要的 go 例程已經在偵聽先前的零值。在這個新通道上發送也會永遠阻塞,因為它沒有讀取任何內容,所以所有 goroutine 都會阻塞。

要解決這個問題,請移到m[0] = make(chan string)你的 go 例程之上,這樣它就會同步發生。


查看完整回答
反對 回復 2022-10-10
  • 2 回答
  • 0 關注
  • 126 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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