go - 在缓冲 channel 上使用范围时程序中的死锁

标签 go channel goroutine

我正在学习 Go,并且正在玩 Goroutines 和 channel 。我正在使用两个缓冲 channel 编写一个非常人为和天真的工作池,一个用于输入,一个用于输出。

现在我在添加作业后关闭我的输入 channel ,然后最终读取输出 channel 以从中读取结果,但是当我使用 for val := range ch 作为输出时程序因死锁而 panic 。这是示例代码

package main

import (
    "fmt"
    "time"
)

func main() {
    st := time.Now()

    jobs := make(chan int, 100)
    res := make(chan int, 100)

    // Putting items to the jobs channel
    for i := 0; i < 9; i++ {
        jobs <- i
    }
    close(jobs)

    go workerPool(jobs, res, 1)


    // This causes the program to panic with deadlock
    for v := range res {
        fmt.Println(v)
    }

// This works just fine and program does not panics
    //for i := 0; i < 9; i++ {
    //  fmt.Println(<-res)
    //}

    ed := time.Now()
    fmt.Println(ed.Sub(st))
}

func workerPool(ip <-chan int, op chan<- int, id int) {
    for v := range ip {
        fmt.Println("Worker", id, "working on ", v)
        op <- 1
    }
}

这是我看到的输出

Worker 1 working on  0
Worker 1 working on  1
Worker 1 working on  2
Worker 1 working on  3
Worker 1 working on  4
Worker 1 working on  5
Worker 1 working on  6
Worker 1 working on  7
Worker 1 working on  8
1
1
1
1
1
1
1
1
1
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.main()

我知道当我使用传统的 for 循环 时,我正在获取我最初放入 jobs channel 的确切数量的值 (9)。但是 for range 不应该自动处理这个问题吗?当没有更多数据要从 channel 读取时, channel 将发送 false 值并且循环将终止?

最佳答案

这个问题的解决方案非常明显,我所要做的就是关闭 worker 中的输出 channel ,range 开始正常工作,原因很明显。

func workerPool(ip <-chan int, op chan<- int, id int) {
    for v := range ip {
        fmt.Println("Worker", id, "working on ", v)
        op <- fib(v)
    }
    close(op) // change made 
}

关于go - 在缓冲 channel 上使用范围时程序中的死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55852807/

相关文章:

concurrency - 两个例程在同一个 channel 上通信

golang 模块名称更改导致本地测试失败

go - 命名空间路由

c - 集成到静态库中的可重定位列表

go - 在 golang 模板之间共享变量

flash - channel.position永远不会等于as3中的sound.length

unit-testing - 如何在并行Go测试中正确使用 channel ?

go - 一个 channel 操作是否影响另一个 channel 操作

google-app-engine - App Engine 转到 : How to kill a running goroutine

go - 为什么在 runtime.GOMAXPROCS(1) 时单个 goroutine 比多个 goroutine 运行得慢?