тупик при передаче канала в качестве аргумента в конвейере - PullRequest
0 голосов
/ 26 февраля 2019

Я кодирую практику разделения числа на 100 групп и одновременного вычисления факториала, однако мой код дает мне тупик.

Я думаю, что проблема может быть в инициации цепочки конвейера.Поскольку все функции принимают в качестве аргумента каналы, я не понимаю, почему функция go fun в main не передает заданное in значение канала функции genConcurrentGroup, когда эта строка total:= <- c происходит.

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 Ответ

0 голосов
/ 26 февраля 2019

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

Вам необходимо добавить буфер в ваш in канал, потому что никто не получает при отправке значения.

enter image description here

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

Вам нужно добавить sync.WaitGroup, чтобы дождаться окончания всех процедур, а затем вы можете закрыть свой канал, чтобы зациклить его.

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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...