第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

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

“消費或放回”轉(zhuǎn)到頻道

“消費或放回”轉(zhuǎn)到頻道

Go
幕布斯7119047 2021-12-06 16:35:44
我試圖有兩個單獨的消費者 go 例程,它會從輸入通道中過濾掉偶數(shù)和奇數(shù)。這只是一個玩具示例,目的是查看是否有可能讓消費者對從輸入通道讀取的消息在匹配特定條件時執(zhí)行某些操作,否則將其放回輸入通道。我目前的代碼如下:package mainfunc filterOdd(ch chan int, out chan int) {    val := <- ch    if val % 2 == 0 {        ch <- val    } else {        out <- val    }}func filterEven(ch chan int, out chan int) {    val := <- ch    if val % 2 != 0 {        ch <- val    } else {        out <- val    }}func main() {    even := make(chan int)    odd := make(chan int)    input := make(chan int)    go filterOdd(input, odd)    go filterEven(input, even)    for i:=1; i <= 10; i++ {        input <- i    }    println("Even...")    for i := range even {        println(i)    }    println("Odd...")    for i := range odd {        println(i)    }}但是,這會產(chǎn)生以下輸出:fatal error: all goroutines are asleep - deadlock!goroutine 1 [chan send]:main.main()    /tmp/sandbox594577124/main.go:27 +0x140goroutine 4 [chan send]:main.filterOdd(0x10336100, 0x103360c0)    /tmp/sandbox594577124/main.go:8 +0xc0created by main.main    /tmp/sandbox594577124/main.go:24 +0xc0Go Playground 鏈接:https : //play.golang.org/p/9RIvFsGKI-
查看完整描述

1 回答

?
森林海

TA貢獻2011條經(jīng)驗 獲得超2個贊

你有一個死鎖,因為你的偶數(shù)和奇數(shù) goroutines 在發(fā)送到時被阻止,out因為沒有從中讀取任何內(nèi)容。為什么什么都不讀out?因為maingoroutine 在發(fā)送到時被阻止,input因為沒有從中讀取任何內(nèi)容。為什么沒有讀取input?因為從中讀取的兩個 goroutine 被阻塞了。

此外,除非您將它們的內(nèi)容包裝在其中,否則它們filterEvenfilterOdd都只會運行一次for { }(但是在您之前它們永遠不會停止break)。另一方面,當沒有任何東西可以寫入時,range even將阻塞(并且range odd永遠不會發(fā)生)even,因為range只有當通道關(guān)閉或被break調(diào)用時,通道才會停止。

一般來說,只要您知道何時可以關(guān)閉通道,這些都不是很難解決的問題。根據(jù)您的描述,這變得更加困難。沒有一個 goroutine 知道什么時候可以關(guān)閉input,因為所有三個都向它寫入,兩個也從它讀取。您可以使用 async.WaitGroup來確保input在關(guān)閉之前已處理您放入通道的所有內(nèi)容。一旦它關(guān)閉,另外兩個 goroutine 就可以使用它作為關(guān)閉它們自己的通道breakreturn完成運行的信號。

但是,對inout通道的寫入仍然會阻塞,直到有相應(yīng)的讀取,因為它們是無緩沖的。但是,如果您通過將大小指定為 的第二個參數(shù)來緩沖它們,則make在通道已滿之前不會阻止寫入。既然你既不知道evenodd將有更多的寫入他們比什么maininput,你可以使用它作為安全緩沖能力。

這是WaitGroup為您的代碼使用帶緩沖通道的示例:https : //play.golang.org/p/VXqfwUwRcx

如果您不想要緩沖通道,您還可以使用另一對 goroutines 來捕獲值并main在完成后將它們作為切片發(fā)送回。這種方式寫在evenodd渠道不會阻塞:https://play.golang.org/p/i5vLDcsK1v

否則,如果不需要一次打印每個頻道的內(nèi)容,您可以使用這兩個額外的 goroutine 從頻道中讀取并立即打印:https : //play.golang.org/p/OCaUTcJkKB


查看完整回答
反對 回復 2021-12-06
  • 1 回答
  • 0 關(guān)注
  • 154 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號