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

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

致命錯誤:所有 goroutine 都在睡覺 - 死鎖!將 WaitGroup

致命錯誤:所有 goroutine 都在睡覺 - 死鎖!將 WaitGroup

Go
函數式編程 2023-07-31 10:51:14
go版本: go1.12.5 linux/amd64我試圖理解 Go 中的 nil 通道。package mainimport (    "fmt"    "sync")func main() {    ch := make(chan int)    ch2 := make(chan int)    wg := sync.WaitGroup{}    wg.Add(1)    go func(c1 chan int, c2 chan int, w *sync.WaitGroup) {        for c1 != nil || c2 != nil {            fmt.Println("in for")            fmt.Println(c1, c2)            select {            case v, ok := <-c1:                if !ok {                    c1 = nil                    fmt.Println("c1 closed")                } else {                    fmt.Println(v, " recieved c1")                }            case v, ok := <-c2:                if !ok {                    c2 = nil                } else {                    fmt.Println(v, " recieved c2")                }            }        }        fmt.Println("called wg.Done")        wg.Done()    }(ch, ch2, &wg)    for i := 0; i < 4; i++ {        if i%2 == 0 {            ch <- i        } else {            ch2 <- i        }    }    close(ch)    wg.Wait()}并在標準輸出上收到此輸出:in for0xc000084060 0xc0000840c00  recieved c1in for0xc000084060 0xc0000840c01  recieved c2in for0xc000084060 0xc0000840c02  recieved c1in for0xc000084060 0xc0000840c03  recieved c2in for0xc000084060 0xc0000840c0c1 closedin for<nil> 0xc0000840c0fatal error: all goroutines are asleep - deadlock!goroutine 1 [semacquire]:sync.runtime_Semacquire(0xc00009a018)        /usr/local/go/src/runtime/sema.go:56 +0x39sync.(*WaitGroup).Wait(0xc00009a010)        /usr/local/go/src/sync/waitgroup.go:130 +0x65main.main()        /home/ayush/projects/gojects/src/go-practice/nil-channels/main.go:44 +0x155goroutine 18 [select]:main.main.func1(0xc00009a010, 0xc000084060, 0xc0000840c0, 0xc00009a010)        /home/ayush/projects/gojects/src/go-practice/nil-channels/main.go:17 +0x1e5created by main.main        /home/ayush/projects/gojects/src/go-practice/nil-channels/main.go:13 +0xceexit status 2但根據代碼和日志,wg.Done()從未被調用過,這意味著 goroutine 仍然存在。誰能幫我理解這里發生了什么?
查看完整描述

2 回答

?
慕沐林林

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

你只有靠近ch,沒有ch2。當ch關閉時,goroutine 設置c1為 nil,但c2仍然不是 nil,因此select等待從 接收c2,而主 goroutine 等待wg.Done(),因此兩個 goroutine 都處于睡眠狀態。



查看完整回答
反對 回復 2023-07-31
?
人到中年有點甜

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

這是因為你沒有關閉而發生的ch2。選擇塊仍在等待ch2。


工作代碼:


package main


import (

    "fmt"

    "sync"

)


func main() {

    ch := make(chan int)

    ch2 := make(chan int)

    wg := sync.WaitGroup{}

    wg.Add(1)


    go func(c1 chan int, c2 chan int, w *sync.WaitGroup) {

        for c1 != nil || c2 != nil {


            select {

            case v, ok := <-c1:

                if !ok {

                    c1 = nil

                    fmt.Println("c1 closed")

                } else {

                    fmt.Println(v, " recieved c1")

                }

            case v, ok := <-c2:

                if !ok {

                    c2 = nil

                } else {

                    fmt.Println(v, " recieved c2")

                }

            }

        }


        fmt.Println("called wg.Done")

        wg.Done()

    }(ch, ch2, &wg)


    for i := 0; i < 4; i++ {

        if i%2 == 0 {

            ch <- i

            fmt.Println("sending to c1 ", i)

        } else {

            ch2 <- i

            fmt.Println("sending to c2 ", i)

        }

    }

    close(ch)

    close(ch2)

    wg.Wait()

}



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

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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