在pipline中将通道作为参数传递时出现死锁

时间:2019-02-26 11:05:52

标签: go

我正在编写一种将数字分为100组并同时计算阶乘的实践,但是我的代码给了我僵局。

我认为问题可能在于管道链的启动。由于所有函数都将通道作为参数,因此我不清楚为什么在主行{{1}时main中的go func不能将给定的in通道值传递给genConcurrentGroup函数}。

total:= <- c

1 个答案:

答案 0 :(得分:0)

1。 total:= <- c //DEADLOCK HERE! Why?

您需要向in频道添加一个缓冲区,因为发送该值时没有人收到。

enter image description here

2。 total := <-nums //DEADLOCK HERE! Why?

您需要添加sync.WaitGroup以等待所有goroutine结束,然后您可以关闭频道以对其进行循环。

enter image description here

没有死锁的完整代码:

package main

import (
    "fmt"
    "sync"
)

func main() {
    in := make(chan int, 1)

    in <- 1005
    out := calculateFacotorial(genConcurrentGroup(in))

    fmt.Println(<-out)

}

//split input number into groups
//the result should be a map of [start number, number in group]
//this is not heavy task so run in one go routine
func genConcurrentGroup(c chan int) chan map[int]int {
    out := make(chan map[int]int)

    go func() {
        //100 groups
        total := <-c //DEADLOCK HERE! Why?
        //element number in group
        elemNumber := total / 100
        extra := total % 100
        result := make(map[int]int)
        if elemNumber > 0 {
            //certain 100 groups
            for i := 1; i <= 99; i++ {
                result[(i-1)*elemNumber+1] = elemNumber
            }
            result[100] = extra + elemNumber
        } else {
            //less than 100
            for i := 1; i <= total; i++ {
                result[i] = 1
            }
        }

        out <- result
        close(out)
    }()
    return out
}

//takes in all numbers to calculate multiply result
//this could be heavy so can do it 100 groups together
func calculateFacotorial(nums chan map[int]int) chan float64 {
    out := make(chan float64)
    total := <-nums //DEADLOCK HERE! Why?

    go func() {
        oneResult := make(chan float64, len(total))

        var wg sync.WaitGroup
        wg.Add(len(total))

        for k, v := range total {
            go func() {
                t := 1.0
                for i := 0; i < v; i++ {
                    t *= float64(k) + float64(i)
                }
                oneResult <- t
                wg.Done()
            }()
        }

        wg.Wait()

        close(oneResult)

        result := 1.0
        for n := range oneResult {
            result *= n
        }

        out <- result

    }()
    return out
}