Запуск одной и той же go программы многократных бросков pani c: отправка по закрытому каналу - PullRequest
0 голосов
/ 01 мая 2020

Я новичок в golang и пытаюсь понять, как работает workerpool. Следующий пример программы работает нормально, если я запускаю один раз и при попытке запустить несколько раз я получаю pani c: отправить по закрытому каналу ошибка. Go версия go1.14.2

package main
import (
    "fmt"
    "time"
)
func main() {
    jobs := make(chan int, 10)
    results := make(chan int, 10)

    for x := 1; x <= 3; x++ {
        go worker(x, jobs, results)
    }

    for j := 1; j <= 6; j++ {
        jobs <- j
    }
    close(jobs)
    for r:=range results{
        fmt.Println("Result received from worker: ", r)
    }
}
func worker(ID int, jobs <-chan int, results chan<- int) {
    for job := range jobs {
        fmt.Println("Worker ", ID, " is working on job ", job)
        time.Sleep(1000*time.Millisecond)
        fmt.Println("Worker ", ID, " completed work on job ", job)
        results <- job
    }
    close(results)
}

Первый запуск в порядке

go run main.go                                                                            
Worker  3  is working on job  1
Worker  1  is working on job  2
Worker  2  is working on job  3
Worker  2  completed work on job  3
Worker  2  is working on job  4
Result received from worker:  3
Worker  1  completed work on job  2
Worker  1  is working on job  5
Result received from worker:  2
Worker  3  completed work on job  1
Worker  3  is working on job  6
Result received from worker:  1
Worker  3  completed work on job  6
Result received from worker:  6

Второй запуск дает это.

Worker  3  is working on job  2
Worker  2  is working on job  3
Worker  1  is working on job  1
Worker  3  completed work on job  2
Worker  3  is working on job  4
Worker  2  completed work on job  3
Worker  2  is working on job  5
Worker  1  completed work on job  1
Worker  1  is working on job  6
Result received from worker:  2
Result received from worker:  3
Result received from worker:  1
Worker  1  completed work on job  6
Worker  3  completed work on job  4
Result received from worker:  6
panic: send on closed channel

goroutine 35 [running]:
main.worker(0x3, 0xc0000b0000, 0xc0000b00b0)
    /home/jibi_makkar/code/go/src/main.go:30 +0x252
created by main.main
    /home/jibi_makkar/code/go/src/main.go:13 +0xad
exit status 2

Может кто-нибудь помочь мне понять, что происходит?

Ответы [ 2 ]

5 голосов
/ 01 мая 2020

У вас есть несколько процедур, закрывающих канал results.

func worker(ID int, jobs <-chan int, results chan<- int) {
    for job := range jobs {
        fmt.Println("Worker ", ID, " is working on job ", job)
        time.Sleep(1000*time.Millisecond)
        fmt.Println("Worker ", ID, " completed work on job ", job)
        results <- job
    }
    close(results)            <<<<-------- Here
}

Эта функция worker выполняется в трех различных одновременных программах. Первый, достигший отмеченной строки, закрывает канал, а остальные пытаются отправить по закрытому каналу в results <- job в l oop.

1 голос
/ 01 мая 2020

Ответ Эли Бендерски описывает проблему. Этот ответ описывает исправление. Я знаю, что вы не просили исправить, но я предполагаю, что вы заинтересованы. Итак, вот оно.

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

var wg sync.WaitGroup
for x := 1; x <= 3; x++ {
    wg.Add(1)  // increment worker counter
    go func(x int) {
        defer wg.Done() // decrement on return from goroutine
        worker(x, jobs, results)
    }(x)
}

// Close results channel when workers are done.
go func() {
    wg.Wait()
    close(results)
}()

Запустите эту программу GoLANG на PlayGround: https://play.golang.org/p/GM-0Gqx0Gbg

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...