2017-10-01 71 views
0

我正在嘗試使用因子問題的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 
} 

我已經提出了評論,以便它更容易遵循代碼。

回答

0

我不是渠道專家。我已經接受了這個嘗試,並更熟悉去。 另一個問題是int不夠大,無法將所有階乘採用20個左右。 如您所見,我在generator func中添加了一個延遲關閉以及一個名爲done的邏輯通道。剩下的更改可能不需要。使用頻道時,您需要確保在頻道上放置某些內容時,可以準備好在頻道上取消某個值。否則會造成死鎖。此外,使用

去運行,-RACE main.go

有助於至少看到其線(S)是問題的根源。

我希望這有助於不被刪除,因爲脫離主題。

我能夠這樣做是爲了去除僵局:

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 
}