golang goroutines, chanel и syn c .WaitGroup - PullRequest
2 голосов
/ 24 апреля 2020

Я использую простой код, но все время захожу в тупик. Пожалуйста, объясните новичку, что я делаю неправильно.

package main

import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup

    ok := make(chan int, 3)
    for i := 0; i < 2; i++ {
        wg.Add(1)

        go func(i int, wg *sync.WaitGroup) {
            for x := range ok {
                fmt.Println(i, x)
                if x >= 5 {
                    ok <- x - 1
                }
            }
            wg.Done()
        }(i, &wg)
    }

    ok <- 1
    ok <- 3
    ok <- 2
    ok <- 5
    ok <- 3
    ok <- 9

    wg.Wait()
}

фатальная ошибка: все программы спят - тупик!

1 Ответ

1 голос
/ 24 апреля 2020
  • Основой проблемы является то, что оператор диапазона читает канал, пока канал не будет закрыт. Следовательно, диапазон l oop продолжает ожидать большего ввода от канала ok, даже если в какой-то момент больше нет входов. В то же время wg.Wait() ждет, пока финиширует финиш sh. Отсюда тупик!

  • Либо вам придется закрыть канал ok в некоторой точке, где больше нет входящих значений в канал ok.

Или вы можете использовать рабочий пул, например,

package main

import (
    "fmt"
    "strconv"
    "sync"
)

func worker(wg *sync.WaitGroup, ch chan string, i int) {
    defer wg.Done()
    ch <- "worker process value  " + strconv.Itoa(i)
}

func workerMonitor(wg *sync.WaitGroup, ch chan string) {
    wg.Wait()
    close(ch)
}

func doWork(ch <-chan string, done chan<- bool) {
    for i := range ch {
        fmt.Println(i)
    }
    done <- true
}

func main() {
    var wg sync.WaitGroup
    ch := make(chan string)
    var arr = [6]int{1, 3, 2, 5, 3, 9}
    for i := 0; i < len(arr); i++ {
        wg.Add(1)
        if arr[i] >= 5 {
            for j := arr[i]; j >= 5; j-- {
                wg.Add(1)
                go worker(&wg, ch, j-1)
            }
        }
        go worker(&wg, ch, arr[i])
    }

    go workerMonitor(&wg, ch)

    done := make(chan bool, 1)
    go doWork(ch, done)
    <-done
}

URL игровой площадки

...