3 回答

TA貢獻1816條經驗 獲得超4個贊
致命錯誤:所有 goroutine 都處于休眠狀態 - 死鎖!
完整的錯誤顯示了每個 goroutine “卡住”的位置。 如果你在操場上運行它,它甚至會顯示你的行號。這讓我很容易診斷。
您Run_parallel
在main
groutine 中運行,因此在main
可以讀取之前out
,Run_parallel
必須返回。在Run_parallel
可以返回之前,它必須wg.Wait()
。但在工人打電話之前wg.Done()
,他們必須寫信給out
。這就是導致僵局的原因。
一種解決方案很簡單:只需Run_parallel
在自己的 Goroutine 中并發運行。
go Run_parallel(NW, in, out, Worker)
現在,main
range over out
,等待out
s 關閉以發出完成信號。 Run_parallel
等待工人與wg.Wait()
,工人將范圍內in
。所有的工作都會完成,并且在完成之前程序不會結束。(https://go.dev/play/p/oMrgH2U09tQ)

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 - - -")
}

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 - - -")
}
- 3 回答
- 0 關注
- 101 瀏覽
添加回答
舉報