duancuisan2503 2017-10-01 07:53
浏览 29

当我尝试模拟风扇输入时出现死锁-通过阶乘计算扇出

I am trying the fan in - fan out pattern with a factorial problem. But I am getting:

fatal error: all goroutines are asleep - deadlock!

and unable to identify the reason for deadlock.

I am trying to concurrently calculate factorial for 100 numbers using the fan-in fan-out pattern.

package main

import (
    "fmt"
)

func main() {
    _inChannel := _inListener(generator())
    for val := range _inChannel {
        fmt.Print(val, " -- ")
    }
}

func generator() chan int { // NEED TO CALCULATE FACTORIAL FOR 100 NUMBERS
    ch := make(chan int) // CREATE CHANNEL TO INPUT NUMBERS

    go func() {
        for i := 1; i <= 100; i++ {
            ch <- i
        }
        close(ch) // CLOSE CHANNEL WHEN ALL NUMBERS HAVE BEEN WRITTEM
    }()

    return ch
}

func _inListener(ch chan int) chan int {
    rec := make(chan int) // CHANNEL RECEIVED FROM GENERATOR
    go func() {
        for num := range ch { // RECEIVE THE INPUT NUMBERS FROM GENERATOR
            result := factorial(num) // RESULT IS A NEW CHANNEL CREATED
            rec <- <-result // MERGE INTO A SINGLE CHANNEL; rec
            close(result)
        }
        close(rec)
    }()
    return rec // RETURN THE DEDICATED CHANNEL TO RECEIVE ALL OUTPUTS
}

func factorial(n int) chan int {
    ch := make(chan int) // MAKE A NEW CHANNEL TO OUTPUT THE RESULT 
    // OF FACTORIAL
    total := 1
    for i := n; i > 0; i-- {
        total *= i
    }
    ch <- total
    return ch // RETURN THE CHANNEL HAVING THE FACTORIAL CALCULATED
}

I have put in comments, so that it becomes easier to follow the code.

  • 写回答

1条回答 默认 最新

  • douliaodun9153 2018-02-08 03:24
    关注

    I'm no expert in channels. I've taking on this to try and get more familiar with go. Another issue is the int isn't large enough to take all factorials over 20 or so. As you can see, I added a defer close as well as a logical channel called done in the generator func. The rest of the changes probably aren't needed. With channels you need to make sure something is ready to take off a value on the channel when you put something on a channel. Otherwise deadlock. Also, using

    go run -race main.go

    helps at least see which line(s) are causing problems.

    I hope this helps and isn't removed for being off topic.

    I was able to remove the deadlock by doing this:

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        _gen := generator()
        _inChannel := _inListener(_gen)
        for val := range _inChannel {
            fmt.Print(val, " -- 
    ")
        }
    }
    
    func generator() chan int { // NEED TO CALCULATE FACTORIAL FOR 100 NUMBERS
        ch := make(chan int) // CREATE CHANNEL TO INPUT NUMBERS
        done := make(chan bool)
        go func() {
            defer close(ch)
            for i := 1; i <= 100; i++ {
                ch <- i
            }
            //close(ch) // CLOSE CHANNEL WHEN ALL NUMBERS HAVE BEEN WRITTEM
            done <- true
        }()
    
        // this function will pull off the done for each function call above.
        go func() {
            for i := 1; i < 100; i++ {
                <-done
            }
        }()
    
        return ch
    }
    
    func _inListener(ch chan int) chan int {
        rec := make(chan int) // CHANNEL RECEIVED FROM GENERATOR
        go func() {
            for num := range ch { // RECEIVE THE INPUT NUMBERS FROM GENERATOR
                result := factorial(num) // RESULT IS A NEW CHANNEL CREATED
                rec <- result            // MERGE INTO A SINGLE CHANNEL; rec
            }
            close(rec)
        }()
    
        return rec // RETURN THE DEDICATED CHANNEL TO RECEIVE ALL OUTPUTS
    }
    
    func factorial(n int) int {
        // OF FACTORIAL
        total := 1
        for i := n; i > 0; i-- {
            total *= i
        }
        return total // RETURN THE CHANNEL HAVING THE FACTORIAL CALCULATED
    }
    
    评论

报告相同问题?

悬赏问题

  • ¥15 msix packaging tool打包问题
  • ¥28 微信小程序开发页面布局没问题,真机调试的时候页面布局就乱了
  • ¥15 python的qt5界面
  • ¥15 无线电能传输系统MATLAB仿真问题
  • ¥50 如何用脚本实现输入法的热键设置
  • ¥20 我想使用一些网络协议或者部分协议也行,主要想实现类似于traceroute的一定步长内的路由拓扑功能
  • ¥30 深度学习,前后端连接
  • ¥15 孟德尔随机化结果不一致
  • ¥15 apm2.8飞控罗盘bad health,加速度计校准失败
  • ¥15 求解O-S方程的特征值问题给出边界层布拉休斯平行流的中性曲线