Проблема параллелизма на каналах Голанг - PullRequest
3 голосов
/ 16 апреля 2019

Я экспериментирую с концепцией канала в Голанге.Я написал ниже программу детская площадка для реализации счетчика с использованием каналов.Но я не получаю никакого вывода, хотя я делаю некоторую печать в теле goroutine.

func main() {
    wg := sync.WaitGroup{}
    ch := make(chan int)

    count := func(ch chan int) {
        var last int
        last = <-ch
        last = last + 1
        fmt.Println(last)
        ch <- last
        wg.Done()
    }

    wg.Add(10)
    for i := 1; i <= 10; i++ {
        go count(ch)

    }
}

Я ожидаю, по крайней мере, некоторый вывод, но я вообще ничего не получаю.

Ответы [ 2 ]

8 голосов
/ 16 апреля 2019

Когда заканчивается функция main() (процедура main), ваша программа также завершается (она не ожидает завершения других операций, отличных от main).Вы должны добавить wg.Wait() звонок до конца.См. Нет вывода из goroutine в Go .

Как только вы это сделаете, вы попадете в тупик.Это связано с тем, что все процедуры начинаются с попытки получить значение из канала, и только тогда они отправляют что-либо.

Таким образом, вы должны сначала отправить что-то по каналу, чтобы позволить по крайней мере одной из программ продолжить работу.

Как только вы это сделаете, вы увидите числа, напечатанные 10 раз, и снова тупик.Это связано с тем, что когда последняя программа пытается отправить свой увеличенный номер, никто не сможет его получить.Самый простой способ исправить это - дать канал каналу.

Окончательный рабочий пример:

wg := sync.WaitGroup{}
ch := make(chan int, 2)

count := func(ch chan int) {
    var last int
    last = <-ch
    last = last + 1
    fmt.Println(last)
    ch <- last
    wg.Done()
}

wg.Add(10)
for i := 1; i <= 10; i++ {
    go count(ch)

}
go func() {
    ch <- 0
}()
wg.Wait()

Выходы (попробуйте на Go Playground ):

1
2
3
4
5
6
7
8
9
10

Также обратите внимание, что, поскольку мы сделали канал буферизованным, нет необходимости использовать другую процедуру для отправки начального значения, мы можем сделать это в процедуре main:

ch <- 0
wg.Wait()

Это выдаст то же самое.Попробуйте это на игровой площадке Go .

1 голос
/ 06 июня 2019
func main() {
    wg := sync.WaitGroup{}
    ch := make(chan int)

    count := func(ch chan int) {
        var last int
        last, ok := <-ch // 这里做一层保护
        if !ok {
            return
        }

        last = last + 1
        fmt.Println(last)

        go func(ch chan int, res int) {
            ch <- res
        }(ch, last)

        wg.Done()
    }

    go func() {
        ch <- 0
    }()

    wg.Add(10)
    for i := 1; i <= 10; i++ {
        go count(ch)
    }

    wg.Wait()

    fmt.Println("main finish")
    close(ch)
}
...