为了账号安全,请及时绑定邮箱和手机立即绑定

多次运行同一个 go 程序会引发恐慌:在关闭的通道上发送

多次运行同一个 go 程序会引发恐慌:在关闭的通道上发送

Go
皈依舞 2022-06-01 16:03:45
我是 golang 的新手,并试图了解 workerpool 的工作原理。如果我运行一次并且尝试多次运行我会感到恐慌,则以下示例程序可以正常工作:发送关闭通道错误。Go 版本是 go1.14.2package mainimport (    "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  1Worker  1  is working on job  2Worker  2  is working on job  3Worker  2  completed work on job  3Worker  2  is working on job  4Result received from worker:  3Worker  1  completed work on job  2Worker  1  is working on job  5Result received from worker:  2Worker  3  completed work on job  1Worker  3  is working on job  6Result received from worker:  1Worker  3  completed work on job  6Result received from worker:  6第二次运行给出了这个。Worker  3  is working on job  2Worker  2  is working on job  3Worker  1  is working on job  1Worker  3  completed work on job  2Worker  3  is working on job  4Worker  2  completed work on job  3Worker  2  is working on job  5Worker  1  completed work on job  1Worker  1  is working on job  6Result received from worker:  2Result received from worker:  3Result received from worker:  1Worker  1  completed work on job  6Worker  3  completed work on job  4Result received from worker:  6panic: send on closed channel谁能帮我理解发生了什么?
查看完整描述

2 回答

?
临摹微笑

TA贡献1982条经验 获得超2个赞

您有多个关闭results通道的 goroutine。


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你在三个不同的并发 goroutine 中运行这个函数。第一个到达标记线的人关闭通道,其他人尝试results <- job在循环中的关闭通道上发送。


查看完整回答
反对 回复 2022-06-01
?
眼眸繁星

TA贡献1873条经验 获得超9个赞

Eli Bendersky 的回答描述了这个问题。这个答案描述了修复。我知道你没有要求修复,但我假设你有兴趣。所以就在这里。


修复方法是在关闭通道之前等待工作 goroutine 完成。使用sync.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)

}()

在 PlayGround 上运行这个 GoLANG 程序:https: //play.golang.org/p/GM-0Gqx0Gbg


查看完整回答
反对 回复 2022-06-01
  • 2 回答
  • 0 关注
  • 179 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号