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

时间:2019-04-25 15:27:09

标签: go channel goroutine

我正在学习Go,并且正在使用Goroutine和频道。我当时使用两个缓冲通道(一个用于输入,一个用于输出)编写了一个非常人性化的天真工作池。

现在,我在向其添加作业之后关闭了输入通道,然后最终读取了输出通道以从中读取结果,但是,当我使用let convertedDate; if (isNaN(myDate)) { convertedDate = moment(myDate,'MMM/dd/yyyy').format('YYYYDDMMHHmmss'); } else { convertedDate = myDate; // already in YYYYDDMMHHmmss format like date1 } 导致输出程序出现死锁时会出现恐慌。这是示例代码

for val := range ch

这是我看到的输出

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 loop通道中的值的准确数量(9)。但是jobs是否应该自动处理此问题,即当没有更多数据要从通道读取时,通道将发送for range值并且循环将终止?

1 个答案:

答案 0 :(得分:0)

解决方案非常明显,我要做的就是close工作者中的输出通道,并且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 
}