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

使用等待组的 Golang 工作者

使用等待组的 Golang 工作者

Go
明月笑刀无情 2022-10-10 16:59:54
我是 Golang 的新手,并试图了解 Golang 中的 WaitGroups 和并发是如何工作的。在此示例中,创建了 5 个工作人员,并使用一个通道将工作传递给每个工作人员。工作人员被要求休眠 1 秒以模拟繁重的计算。一切顺利,但程序并没有优雅地退出。而是打印此错误消息。请帮助理解为什么会发生这种情况。fatal error: all goroutines are asleep - deadlock!这是代码,import (    "fmt"    "sync"    "time")func worker(wg *sync.WaitGroup, messageChannel <-chan string) {    defer wg.Done()    for i := range messageChannel {        time.Sleep(time.Second)        fmt.Println("done processing - ", i)    }}func stop(wg *sync.WaitGroup) {    fmt.Println("waiting on the main thread")    wg.Wait()}func main() {    wg := new(sync.WaitGroup)    messageChannel := make(chan string, 50)    // create workers    for i := 0; i < 5; i++ {        wg.Add(1)        go worker(wg, messageChannel)    }    // input some messages    for i := 0; i < 10; i++ {        messageChannel <- fmt.Sprint(i)    }    stop(wg)    close(messageChannel)}提前致谢!
查看完整描述

1 回答

?
汪汪一只猫

TA贡献1898条经验 获得超8个赞

为了扩展@Peter 的评论,这里是您编写的代码的执行流程:

  • 初始化后,你启动你的workergoroutines。每个workergoroutine 都会超过messageChannel,延迟 1 秒会打印出一条消息。

  • 接下来,您messageChannel通过 for 循环插入一些消息。每个可用worker的 goroutine 都会收到一条消息,直到所有消息都被处理并打印出来。之后,workergoroutines 正在等待来自messageChannel.

  • 在用于在中插入消息的 for 循环messageChannel完成后,您执行该stop函数,该函数阻塞wg.Wait()并等待所有wg.Done()调用在所有workergoroutine 中执行。然而,由于messageChannel没有关闭,没有一个workergoroutine 可以完成执行,也没有一个wg.Done()调用被执行。

  • workergoroutines 被卡住是因为它messageChannel永远不会关闭,maingoroutines 因为函数wg.Wait()内部的调用而被卡住stop,你最终会陷入一个所有 goroutines 都处于休眠状态的死锁。

根据建议,您只需要交换地点stopclose电话

//rest of the code

close(messageChannel)

stop(wg)

这样,当所有消息都插入到 中时messageChannel,您调用close(messageChannel)然后stop(wg),这会阻塞wg.Wait调用。该close(messageChannel)调用确保,一旦从 中读取所有消息messageChannel,goroutine内部的for-range循环将退出,并且所有调用都将被执行。一旦发生这种情况,将解除阻塞,程序将正确完成执行。messageChannelworkerdefer wg.Done()wg.Wait()


查看完整回答
反对 回复 2022-10-10
  • 1 回答
  • 0 关注
  • 69 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信