使用等待组的 Golang 工作者

我是 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)

}

提前致谢!


明月笑刀无情
浏览 88回答 1
1回答

汪汪一只猫

为了扩展@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 都处于休眠状态的死锁。根据建议,您只需要交换地点stop和close电话//rest of the codeclose(messageChannel)stop(wg)这样,当所有消息都插入到 中时messageChannel,您调用close(messageChannel)然后stop(wg),这会阻塞wg.Wait调用。该close(messageChannel)调用确保,一旦从 中读取所有消息messageChannel,goroutine内部的for-range循环将退出,并且所有调用都将被执行。一旦发生这种情况,将解除阻塞,程序将正确完成执行。messageChannelworkerdefer wg.Done()wg.Wait()
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go