【问题标题】:Getting deadlock as I try to emulate fan in - fan out with factorial calculations当我尝试模拟扇入时陷入僵局 - 使用阶乘计算扇出
【发布时间】:2018-03-12 15:05:47
【问题描述】:

我正在尝试带有阶乘问题的 fan in - fan out 模式。但我得到:

fatal error: all goroutines are asleep - deadlock!

并且无法确定死锁的原因。

我正在尝试使用扇入扇出模式同时计算 100 个数字的阶乘。

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
}

我已经放入了cmets,这样更容易看代码。

【问题讨论】:

    标签: go concurrency deadlock channel


    【解决方案1】:

    我不是渠道专家。我已经开始尝试并更熟悉 go。 另一个问题是 int 不够大,无法将所有阶乘超过 20 左右。 如您所见,我在生成器函数中添加了一个延迟关闭以及一个名为 done 的逻辑通道。其余的更改可能不需要。对于通道,您需要确保当您将某些内容放在通道上时,某些内容已准备好在通道上取得价值。否则死锁。另外,使用

    运行 -race main.go

    至少有助于查看哪些线路引起了问题。

    我希望这会有所帮助,并且不会因为离题而被删除。

    我可以通过这样做来消除死锁:

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        _gen := generator()
        _inChannel := _inListener(_gen)
        for val := range _inChannel {
            fmt.Print(val, " -- \n")
        }
    }
    
    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
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-01-06
      • 2017-07-28
      • 2020-08-25
      • 1970-01-01
      • 2022-07-14
      • 2019-12-20
      • 1970-01-01
      相关资源
      最近更新 更多