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

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

無法處理 goroutine 死鎖

無法處理 goroutine 死鎖

Go
慕村9548890 2023-08-14 16:47:03
我正在嘗試向某個頻道廣播一條消息,我只想讓它發送 5 條消息。但我總是收到這個錯誤: 致命錯誤:所有 goroutine 都在睡覺 - 死鎖!我的代碼:package mainimport (    "log"    "sync"    broadcast "github.com/dustin/go-broadcast"    "github.com/pwaller/barrier")//Message boradcastedtype Message struct {    y string    x int}var w sync.WaitGroupvar bar barrier.Barrierfunc main() {    b := broadcast.NewBroadcaster(100)    w.Add(1)    go workerOne(b)    d := Message{"message :", 0}    go func() {        for i := 0; i < 5; i++ {            d.x = i            log.Printf("Sending %v", d)            b.Submit(d)        }        <-bar.Barrier()        b.Close()    }()    w.Wait()}func workerOne(b broadcast.Broadcaster) {    ch := make(chan interface{})    b.Register(ch)    for {        v, ok := <-ch        if ok {            log.Printf("workerOne() reading : %v", v)        } else {            log.Printf("i am here")            close(ch)            b.Unregister(ch)            bar.Fall()            w.Done()            return        }    }}輸出 :2019/12/26 20:34:11 Sending {message : 0}2019/12/26 20:34:11 Sending {message : 1}2019/12/26 20:34:11 Sending {message : 2}2019/12/26 20:34:11 Sending {message : 3}2019/12/26 20:34:11 Sending {message : 4}2019/12/26 20:34:11 workerOne() reading : {message : 0}2019/12/26 20:34:11 workerOne() reading : {message : 1}2019/12/26 20:34:11 workerOne() reading : {message : 2}2019/12/26 20:34:11 workerOne() reading : {message : 3}2019/12/26 20:34:11 workerOne() reading : {message : 4}fatal error: all goroutines are asleep - deadlock!我嘗試了一切,但它不會在workerOne()函數中拋出條件!ok來關閉通道并結束等待,但仍然有相同的錯誤
查看完整描述

1 回答

?
慕妹3146593

TA貢獻1820條經驗 獲得超9個贊

barrier您正在使用的軟件包已被棄用,取而代之的是 Go 包含的context軟件包。你應該改用context。(broadcast目前,您使用的軟件包也沒有真正給您帶來任何好處。)

不過,眼前的問題似乎非常明顯:運行的(單個)goroutineworkerOne從通道讀取,并且只有當通道關閉(因此ok變為false)時,它才會調用bar.Fall()刪除屏障。同時,(單個)goroutine 運行匿名發送者函數:

go func() {

? ? for i := 0; i < 5; i++ {

? ? ? ? d.x = i

? ? ? ? log.Printf("Sending %v", d)

? ? ? ? b.Submit(d)

? ? }

? ? <-bar.Barrier()

? ? b.Close()

}()

通過包的(非常)簡單的消息發布/訂閱接口提交五個項目broadcast,然后等待屏障下降。唯一能夠放下障礙的 Goroutine(把它想象成唯一能在這里拯救你的地鼠workerOne)就是正在運行的 goroutine 。他現在正在頻道接收中等待:


? ? v, ok := <-ch

您在主 Goroutine 中正在通過sync.WaitGroup變量等待:


w.Wait()

運行匿名發送函數的地鼠正在等待:


? ? <-bar.Barrier()

誰——在不同的 Go 例程中運行或等待的三個地鼠中的哪一個——將向匿名發送者中的地鼠發出信號,應該v, ok := <-ch得到!ok結果?唯一能做到的就是地鼠奔跑workerOne,但他被困住了。


該broadcast軟件包永遠不會為您關閉您的頻道。取消注冊頻道只是將其從廣播公司的輸出頻道中刪除,從而使未注冊的頻道保持開放狀態;完全有效地關閉廣播公司只會注銷所有頻道,再次讓它們保持開放狀態。因此,如果您希望關閉自己的頻道,則必須自己在其他地方執行此操作。


或者,您可以修改您的設置workerOne,使其不依賴于關閉的通道。例如,您的變量d有 anx int和 a y string; 您可以選擇其中一個或兩個,并確定讀取“drop thebarrier”的字符串值(可能int還具有某些特定值)意味著“bar.Fall()立即調用”。如果您這樣做,您從這兩個非標準包中獲得的收益會更少。


查看完整回答
反對 回復 2023-08-14
  • 1 回答
  • 0 關注
  • 183 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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