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

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

得到一個致命錯誤:所有的 goroutine 都睡著了——死鎖!有一個簡單的測試場景

得到一個致命錯誤:所有的 goroutine 都睡著了——死鎖!有一個簡單的測試場景

Go
慕村9548890 2021-12-06 18:35:35
我正在嘗試重現一個問題,并使用以下代碼找到了最小用例。如果我關閉所有通道(繞過 i == 0 測試),一切都會按預期進行。Wg 狀態遞減并觸發完成,主要退出正常。當我跳過關閉這些通道之一(故意)時,我希望主例程等待,而在這種情況下等待組信號量將無限期阻塞。相反,我收到了一個錯誤:“致命錯誤:所有 goroutine 都睡著了 - 死鎖!”。這是為什么?我一定錯過了一些基本的東西,還是運行時過于熱心了?package mainimport (    "fmt"    "sync")const N int = 4func main() {    done := make(chan struct{})    defer close(done)    fmt.Println("Beginning...")    chans := make([]chan int, N)    var wg sync.WaitGroup    for i := 0; i < N; i++ {        wg.Add(1)        chans[i] = make(chan int)        go func(i int) { // p0            defer wg.Done()            for m := range chans[i] {                fmt.Println("Received ", m)            }            fmt.Println("Ending p", i)        }(i)    }    go func() {        wg.Wait()        done <- struct{}{} // signal main that we are done    }()    for i := 0; i < N; i++ {        fmt.Println("Closing c", i)        if i != 0 { // Skip #0 so wg doesn't reach '0'            close(chans[i])        }    }    <-done // wait to receive signal from anonymous join function    fmt.Println("Ending.")}更新:我編輯了代碼以避免競爭條件。仍然收到此錯誤。if i != 0之所以存在,是因為它是故意的。我希望 wg.Wait 永遠阻塞(其信號量永遠不會達到 0。)為什么我不能這樣做?這似乎與我在其他地方<-done沒有匹配的情況下使用done <- struct{}{}一樣。在這種情況下編譯器也會抱怨嗎?
查看完整描述

2 回答

?
小怪獸愛吃肉

TA貢獻1852條經驗 獲得超1個贊

這是發生了什么:

  • 第一個go func(i int) {goroutine 沒有退出,因為chans[0]沒有關閉。

  • 因為 goroutine 沒有退出,wg.Done也沒有被調用。

  • wg.Wait()由于上一點,對永遠阻塞的調用。

  • Main 永遠阻塞,因為信號沒有發送到done。

您可以通過刪除 來解決死鎖if i != 0 {,但還有另一個問題。等待組有一場比賽。有可能在調用 wg.Add(1) 之前調用 wg.Done()。在啟動 goroutine 之前調用 wg.Add() 以避免競爭。


查看完整回答
反對 回復 2021-12-06
?
守著一只汪

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

if你的 for 循環中的語句不會讓最后一個通道關閉,所以你goroutine要等待發生的事情,chans[i]這將阻止defer wg.Done()永遠發生的事情,這反過來永遠不會讓wg.Wait()完成,THENNNNN 永遠不會讓done <- struct{}{}得到信號

簡而言之,您if statement的循環并沒有關閉最后一個通道并導致死鎖,因為沒有人無能為力。

正如@CodingPickle 確實指出的那樣,將您移動wg.Add(1)到您的開頭for loop以防止任何競爭條件

http://play.golang.org/p/j1D5LZGUhd


查看完整回答
反對 回復 2021-12-06
  • 2 回答
  • 0 關注
  • 232 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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