doufang2228 2019-04-25 15:27
浏览 29

在缓冲通道上使用范围时,程序中出现死锁

I am learning Go and was playing with Goroutines and channels. I was writing a very contrived and naive workerpool using two buffered channels one for inputs and one for outputs.

Now I am closing my inputs channel after I add jobs to it and then reading the output channel finally to read the results from it, however when I used for val := range ch for the output program panics with a deadlock. Here is the sample code

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

Here is the output I see

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()

I understand that when I use the conventional for loop I am fetching the exact number of values (9) which I initially put into jobs channel. But isn't for range supposed to handle this automatically that when there is no more data to be read from the channel, the channel will send the false value and the loop will terminate ?

  • 写回答

1条回答 默认 最新

  • doujiao9426 2019-04-26 06:21
    关注

    The solution to this was pretty obvious, all I had to do was close the outputs channel in the worker and range started working correctly for obvious reasons.

    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 
    }
    
    评论

报告相同问题?

悬赏问题

  • ¥15 全部备份安卓app数据包括密码,可以复制到另一手机上运行
  • ¥15 Python3.5 相关代码写作
  • ¥20 测距传感器数据手册i2c
  • ¥15 RPA正常跑,cmd输入cookies跑不出来
  • ¥15 求帮我调试一下freefem代码
  • ¥15 matlab代码解决,怎么运行
  • ¥15 R语言Rstudio突然无法启动
  • ¥15 关于#matlab#的问题:提取2个图像的变量作为另外一个图像像元的移动量,计算新的位置创建新的图像并提取第二个图像的变量到新的图像
  • ¥15 改算法,照着压缩包里边,参考其他代码封装的格式 写到main函数里
  • ¥15 用windows做服务的同志有吗