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

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

嘗試編寫工作方法池時出現死鎖

嘗試編寫工作方法池時出現死鎖

Go
慕森卡 2022-10-17 16:11:22
在下面的代碼中,我不明白為什么“Worker”方法似乎退出而不是從輸入通道“in”中提取值并處理它們。我曾假設他們只會在消耗來自輸入通道“in”的所有輸入并處理它們之后才會返回package mainimport (    "fmt"    "sync")type ParallelCallback func(chan int, chan Result, int, *sync.WaitGroup)type Result struct {    i   int    val int}func Worker(in chan int, out chan Result, id int, wg *sync.WaitGroup) {    for item := range in {        item *= item // returns the square of the input value        fmt.Printf("=> %d: %d\n", id, item)        out <- Result{item, id}    }    wg.Done()    fmt.Printf("%d exiting ", id)}func Run_parallel(n_workers int, in chan int, out chan Result, Worker ParallelCallback) {    wg := sync.WaitGroup{}    for id := 0; id < n_workers; id++ {        fmt.Printf("Starting : %d\n", id)        wg.Add(1)        go Worker(in, out, id, &wg)    }    wg.Wait()  // wait for all workers to complete their tasks    close(out) // close the output channel when all tasks are completed}const (    NW = 4)func main() {    in := make(chan int)    out := make(chan Result)    go func() {        for i := 0; i < 100; i++ {            in <- i        }        close(in)    }()    Run_parallel(NW, in, out, Worker)    for item := range out {        fmt.Printf("From out : %d: %d", item.i, item.val)    }}輸出是Starting : 0Starting : 1Starting : 2Starting : 3=> 3: 0=> 0: 1=> 1: 4=> 2: 9fatal error: all goroutines are asleep - deadlock!
查看完整描述

3 回答

?
繁華開滿天機

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

致命錯誤:所有 goroutine 都處于休眠狀態 - 死鎖!

完整的錯誤顯示了每個 goroutine “卡住”的位置。 如果你在操場上運行它,它甚至會顯示你的行號。這讓我很容易診斷。

Run_parallelmaingroutine 中運行,因此在main可以讀取之前out,Run_parallel必須返回。在Run_parallel可以返回之前,它必須wg.Wait()。但在工人打電話之前wg.Done(),他們必須寫信給out。這就是導致僵局的原因。

一種解決方案很簡單:只需Run_parallel在自己的 Goroutine 中并發運行。

    go Run_parallel(NW, in, out, Worker)

現在,mainrange over out,等待outs 關閉以發出完成信號。 Run_parallel等待工人與wg.Wait(),工人將范圍內in。所有的工作都會完成,并且在完成之前程序不會結束。(https://go.dev/play/p/oMrgH2U09tQ


查看完整回答
反對 回復 2022-10-17
?
暮色呼如

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

解決方案 :


Run_parallel 必須在它自己的 goroutine 中運行:


package main


import (

    "fmt"

    "sync"

)


type ParallelCallback func(chan int, chan Result, int, *sync.WaitGroup)


type Result struct {

    id  int

    val int

}


func Worker(in chan int, out chan Result, id int, wg *sync.WaitGroup) {

    defer wg.Done()

    for item := range in {

        item *= 2 // returns the double of the input value (Bogus handling of data)

        out <- Result{id, item}

    }

}


func Run_parallel(n_workers int, in chan int, out chan Result, Worker ParallelCallback) {

    wg := sync.WaitGroup{}

    for id := 0; id < n_workers; id++ {

        wg.Add(1)

        go Worker(in, out, id, &wg)

    }

    wg.Wait()  // wait for all workers to complete their tasks

    close(out) // close the output channel when all tasks are completed

}


const (

    NW = 8

)


func main() {


    in := make(chan int)

    out := make(chan Result)


    go func() {

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

            in <- i

        }

        close(in)

    }()


    go Run_parallel(NW, in, out, Worker)


    for item := range out {

        fmt.Printf("From out [%d]: %d\n", item.id, item.val)

    }


    println("- - - All done - - -")


}


查看完整回答
反對 回復 2022-10-17
?
絕地無雙

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

解決方案的替代配方:


在那個替代公式中,沒有必要將 Run_parallel 作為 goroutine 啟動(它會觸發自己的 goroutine)。我更喜歡第二種解決方案,因為它自動執行 Run_parallel() 必須與主函數并行運行的事實。此外,出于同樣的原因,它更安全,更不容易出錯(無需記住使用 go 關鍵字運行 Run_parallel)。


package main


import (

    "fmt"

    "sync"

)


type ParallelCallback func(chan int, chan Result, int, *sync.WaitGroup)


type Result struct {

    id  int

    val int

}


func Worker(in chan int, out chan Result, id int, wg *sync.WaitGroup) {

    defer wg.Done()

    for item := range in {

        item *= 2 // returns the double of the input value (Bogus handling of data)

        out <- Result{id, item}

    }

}


func Run_parallel(n_workers int, in chan int, out chan Result, Worker ParallelCallback) {

    go func() {

        wg := sync.WaitGroup{}

        defer close(out) // close the output channel when all tasks are completed

        for id := 0; id < n_workers; id++ {

            wg.Add(1)

            go Worker(in, out, id, &wg)

        }

        wg.Wait() // wait for all workers to complete their tasks *and* trigger the -differed- close(out)

    }()

}


const (

    NW = 8

)


func main() {


    in := make(chan int)

    out := make(chan Result)


    go func() {

        defer close(in)

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

            in <- i

        }

    }()


    Run_parallel(NW, in, out, Worker)


    for item := range out {

        fmt.Printf("From out [%d]: %d\n", item.id, item.val)

    }


    println("- - - All done - - -")

}


查看完整回答
反對 回復 2022-10-17
  • 3 回答
  • 0 關注
  • 101 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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