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

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

goroutines管道中的死鎖

goroutines管道中的死鎖

Go
忽然笑 2022-07-25 11:26:51
我需要你的幫助來理解為什么我的readFromWorkerfunc 會導致死鎖。當我注釋掉下面這樣的行時,它可以正常工作(因此我知道問題就在這里)。整個在這里https://play.golang.org/p/-0mRDAeD2tr我將衷心感謝您的幫助func readFromWorker(inCh <-chan *data, wg *sync.WaitGroup) {    defer func() {        wg.Done()    }()    //stageIn1 := make(chan *data)    //stageOut1 := make(chan *data)    for v := range inCh {        fmt.Println("v", v)        //stageIn1 <- v    }    //go stage1(stageIn1, stageOut1)    //go stage2(stageOut1)}
查看完整描述

1 回答

?
胡子哥哥

TA貢獻1825條經驗 獲得超6個贊

我已經評論了你做錯的相關部分。另外,我建議考慮一個更好的模式。


請記住,for range頻道不會停止循環,除非close它正在循環的同一頻道被調用。此外,關閉通道的經驗法則是發送到通道的發送者也必須關閉它,因為發送到關閉的通道會導致panic.


此外,在使用無緩沖和緩沖通道時要非常小心。對于無緩沖通道,發送方和接收方必須準備好,否則在您的情況下也會發生死鎖。


package main


import (

    "fmt"

    "sync"

)


type data struct {

    id    int

    url   string

    field int

}


type job struct {

    id  int

    url string

}


func sendToWorker(id int, inCh <-chan job, outCh chan<- *data, wg *sync.WaitGroup) {

    // wg.Done() is itself a function call, no need to wrap it inside

    // an anonymous function just to use defer.

    defer wg.Done()


    for v := range inCh {

        // some pre process stuff and then pass to pipeline

        outCh <- &data{id: v.id, url: v.url}

    }

}


func readFromWorker(inCh <-chan *data, wg *sync.WaitGroup) {

    // wg.Done() is itself a function call, no need to wrap it inside

    // an anonymous function just to use defer.

    defer wg.Done()


    var (

        stageIn1  = make(chan *data)

        stageOut1 = make(chan *data)

    )


    // Spawn the goroutines so that there's no deadlock

    // as the sender and receiver both should be ready

    // when using unbuffered channels.

    go stage1(stageIn1, stageOut1)

    go stage2(stageOut1)


    for v := range inCh {

        fmt.Println("v", v)

        stageIn1 <- v

    }

    close(stageIn1)

}


func stage1(in <-chan *data, out chan<- *data) {

    for s := range in {

        fmt.Println("stage1 = ", s)

        out <- s

    }

    // Close the out channel

    close(out)

}


func stage2(out <-chan *data) {

    // Loop until close

    for s := range out {

        fmt.Println("stage2 = ", s)

    }

}


func main() {

    const chanBuffer = 1


    var (

        inputsCh  = make(chan job, chanBuffer)

        resultsCh = make(chan *data, chanBuffer)


        wgInput  sync.WaitGroup

        wgResult sync.WaitGroup

    )


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

        wgInput.Add(1)

        go sendToWorker(i, inputsCh, resultsCh, &wgInput)

    }


    wgResult.Add(1)

    go readFromWorker(resultsCh, &wgResult)


    for j := 1; j <= 10; j++ {

        inputsCh <- job{id: j, url: "google.com"}

    }


    close(inputsCh)

    wgInput.Wait()

    close(resultsCh)

    wgResult.Wait()

}

查看完整回答
反對 回復 2022-07-25
  • 1 回答
  • 0 關注
  • 123 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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