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

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

所有戈魯丁都睡著了 - 死鎖問題

所有戈魯丁都睡著了 - 死鎖問題

Go
慕萊塢森 2022-08-01 10:44:50
我試圖在同步管理器(1,2,3,4...)中打印奇數,使用兩個goroutine,我很困惑為什么我的代碼會導致死鎖。請你能幫我理解嗎?package mainimport (    "fmt"    "sync")var wg sync.WaitGroupfunc odd(ch chan bool){    i :=1    for i<=10{        <-ch        fmt.Println(i)        i+=2        ch<-true    }    wg.Done()}func even(ch chan bool){    i :=2    for i<=10{        <-ch        fmt.Println(i)        i+=2        ch <- true    }    wg.Done()}func main() {    ch :=make(chan bool)    wg.Add(2)    go even(ch)    go odd(ch)    ch <- true    wg.Wait()}O/P: 1 2 3 4 5 6 7 8 9 10 致命錯誤:所有 goroutine 都睡著了 - 死鎖!goroutine 1 [semacquire]: sync.runtime_Semacquire(0x5844a8) /usr/local/go-faketime/src/runtime/sema.go:56 +0x45 sync.(*等待組)。Wait(0x5844a0) /usr/local/go-faketime/src/sync/waitgroup.go:130 +0x65 main.main() /tmp/sandbox505861393/prog.go:37 +0xcfgoroutine 6 [chan send]: main.even(0xc00005e060) /tmp/sandbox505861393/prog.go:26 +0xc5 由 main.main /tmp/sandbox505861393/prog.go:34 +0x7f當我改變 goroutine 的順序時,o/p 開始以奇偶的方式打印,我也很難理解這一點。我將不勝感激你的幫助,謝謝。
查看完整描述

2 回答

?
小唯快跑啊

TA貢獻1863條經驗 獲得超2個贊

如果通道中沒有空間,則在通道上發送也會阻止。如果在通道中使用緩沖區,則發送可以工作。僅使用 1:

ch := make(chan bool, 1)

現在,您可以發送數據,并且它不會阻止go例程,因為它沒有滿。如果您在沒有讀取的情況下再次發送,那么它將阻止發送調用,因為再次沒有空間并且仍然沒有消耗以前的值。

關于打印的順序:沒有順序,其中go例程將首先開始,go lang規范沒有提到多個go例程是否從一個通道接收數據,那么首先等待的人是否真的首先獲得它。因此,如果需要,您需要添加其他同步以維護順序。以下是訂購同步的提示

下面是打印的修改代碼,但我更喜歡不同的方法。檢查上面鏈接中的乒乓球示例,其中使用了2個單獨的通道而不是一個。

package main


import (

    "fmt"

    "sync"

)


func odd(wg *sync.WaitGroup, ch chan bool) {

    defer wg.Done()

    i := 1

    for i <= 10 {

        <-ch

        fmt.Println(i)

        i += 2

        ch <- true

    }

}


func even(wg *sync.WaitGroup, ch chan bool) {

    defer wg.Done()

    i := 2

    for i <= 10 {

        <-ch

        fmt.Println(i)

        i += 2

        ch <- true

    }


}


func main() {

    var wg sync.WaitGroup

    ch := make(chan bool, 1)

    defer close(ch)

    wg.Add(2)

    go even(&wg, ch)

    go odd(&wg, ch)

    ch <- true

    wg.Wait()


}


查看完整回答
反對 回復 2022-08-01
?
犯罪嫌疑人X

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

首先,您的兩個 Goroutine 需要從通道接收才能開始工作ch


for i<=10{

        <-ch // wait until receive

        fmt.Println(i)

        i+=2

        ch <- true

    }

因此,您將值發送到通道,以使兩個 goroutine 工作ch


func main() {

    //...

    ch <- true

    //...

}

但這不會像預期的那樣工作,因為你們的兩個goroutine共享同一個頻道。執行時,只有一個可以接收、開始工作并將值發送回通道。chch <- truemain()ch


之后,兩個 goroutine 不斷從通道接收,開始工作并將值發送回通道ch


換句話說,兩個 goroutine 通過使用通道相互發送和接收值ch


for i<=10 {

    <-ch           // receive when main() executed at first time, after that receive from another goroutine

    fmt.Println(i) // start work

    i+=2           //

    ch <- true     // return back to the channel, another goroutine will receive it

}

wg.Done()

但問題是,當一個goroutine退出時,剩余的goroutine仍然試圖在下班后發送到通道,但沒有接收器,這會導致死鎖ch


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

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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