drl2051 2019-02-26 11:05
浏览 26

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

I'm coding a practice to split number into 100 groups and calculate factorial concurrently, however my code gives me deadlock.

I think the issue could be the pipeline chain initiation. Since all the functions are taking in channels as argument, I'm not clear about why the go func in main doesn't pass the given in channel value to genConcurrentGroup function when this line total:= <- c happens.

package main

import "fmt"

func main() {
    in := make (chan int)
    out := make (chan float64)

    go func() {
        in <- 1005
        out = calculateFacotorial(genConcurrentGroup(in))
    }()

    fmt.Println(<-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)

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

        close(oneResult)
    }()
    return out
}
  • 写回答

1条回答 默认 最新

  • duanlan3598 2019-02-26 13:03
    关注

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

    You need to add a buffer to your in channel because there is nobody receiving when you send the value.

    enter image description here

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

    You need to add a sync.WaitGroup to wait for all goroutines to end and then you can close your channel to loop over it.

    enter image description here

    Complete code without deadlocks:

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

报告相同问题?

悬赏问题

  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度
  • ¥30 关于#r语言#的问题:如何对R语言中mfgarch包中构建的garch-midas模型进行样本内长期波动率预测和样本外长期波动率预测
  • ¥15 ETLCloud 处理json多层级问题
  • ¥15 matlab中使用gurobi时报错
  • ¥15 这个主板怎么能扩出一两个sata口
  • ¥15 不是,这到底错哪儿了😭
  • ¥15 2020长安杯与连接网探
  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么