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

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

Channel 有一個奇怪的行為,為什么要阻止?

Channel 有一個奇怪的行為,為什么要阻止?

Go
HUX布斯 2023-06-01 15:10:23
go 版本 go1.11.4 darwin/amd64創(chuàng)建了一個新的channel和goroutine,通過goroutine將舊channel的內(nèi)容傳輸?shù)絥ew channel。應(yīng)該不會阻塞,但是經(jīng)過測試,發(fā)現(xiàn)是阻塞了。謝謝。type waiter struct {    ch1   chan struct{}    ch2   <-chan time.Time    limit int    count int}func (w *waiter) recv1Block() chan struct{} {    ch := make(chan struct{})    go func() {        for m := range w.ch1 {            ch <- m        }    }()    return ch}func (w *waiter) runBlock(wg *sync.WaitGroup) {    defer wg.Done()    i := 0    for i < w.limit {        select {        case <-w.recv1Block():  **// why block here?**            i++        case <-w.recv2():        }    }    w.count = i}為什么recv1Block會被block。
查看完整描述

1 回答

?
蠱毒傳說

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

每次調(diào)用時recv1Block(),它都會創(chuàng)建一個新通道并啟動一個后臺 goroutine,該 goroutine 會嘗試從中讀取所有數(shù)據(jù)。由于您是在循環(huán)中調(diào)用它,因此您將有很多東西都在嘗試使用通道中的數(shù)據(jù);由于通道永遠不會關(guān)閉,所有的 goroutines 將永遠運行。

作為練習,您可以嘗試更改代碼以傳遞 achan int而不是 a chan struct{},并編寫一系列序列號,并在最終收到時將它們打印出來。像這樣的序列是有效的:

  1. run在 goroutine #1 上調(diào)用recv1Block()。

  2. recv1Block()在 GR#1 上生成 GR#2,并返回通道#2。

  3. run在 GR#1 上阻止在通道#2 上接收。

  4. recv1Block()在 GR#2 上讀取0w.c1.

  5. recv1Block()在 GR#2 上寫入0通道#2(run在 GR#1 上準備好讀?。?。

  6. recv1Block()在 GR#2 上讀取1w.c1.

  7. recv1Block()GR#2 上想要寫入0通道#2 但阻塞了。

  8. runGR#1 上的喚醒,并接收到0。

  9. run在 GR#1 電話上recv1Block()

  10. recv1Block()在 GR#1 上生成 GR#3,并返回通道 #3。

  11. recv1Block()在 GR#3 上讀取2w.c1.

  12. ...

請注意,此序列中的值 1 永遠不會被寫入任何地方,實際上沒有任何東西可以讀取它。

這里的簡單解決方案是不要在循環(huán)中調(diào)用通道創(chuàng)建函數(shù):

func (w *waiter) runBlock(wg *sync.WaitGroup) {

    defer wg.Done()

    ch1 := w.recv1Block()

    ch2 := w.recv2()

    for {

        select {

        case _, ok := <-ch1:

            if !ok {

                return

            }

            w.count++

        case <-ch2:

    }

}

完成頻道后關(guān)閉頻道也是標準做法。這將終止一個for ... range ch循環(huán),并且它看起來對select語句是可讀的。在您的頂級生成器函數(shù)中:


for i := 0; i < w.limit; i++ {

    w.ch1 <- struct{}{}

}

close(w.ch1)

在您的“復制頻道”功能中:


func (w *waiter) recv1Block() chan struct{} {

    ch := make(chan struct{})

    go func() {

        for m := range w.ch1 {

            ch <- m

        }

        close(ch)

    }()

    return ch

}

這也意味著您不需要通過“航位推算”運行主循環(huán),期望它正好產(chǎn)生 100 個項目然后停止;只要它的頻道退出,你就可以停止。我上面顯示的消費者循環(huán)就是這樣做的。


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

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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