登录
首页 >  Golang >  Go问答

问题:当使用例程和通道结合时可能会发生死锁

来源:stackoverflow

时间:2024-03-21 12:09:34 403浏览 收藏

在使用 Go 例程和通道时,如果通道无缓冲且没有其他 goroutine 从该通道接收数据,则可能会发生死锁。这是因为 goroutine 将阻塞在尝试在通道上发送值的行中,而主 goroutine 将等待其他 goroutine 完成。

问题内容

我在使用带有通道的 go 例程时遇到问题。代码如下所示:

func main() {
    c := make(chan int)
    var wg sync.waitgroup

    wg.add(1)
    go func (c chan int, x int) {
        c <- x
        fmt.println(x)
        close(c)

        defer wg.done()
    }(c,10)

    wg.wait()
}

运行代码时出现此错误:

fatal error: all goroutines are asleep - deadlock!

我不明白为什么会出现这个问题。请帮我理解一下


解决方案


您的示例中有 2 个 goroutine:运行 main() 函数的主 goroutine,以及在其中启动的另一个 goroutine。主 goroutine 等待另一个 goroutine 完成(调用 wg.done()),而其他 goroutine 会阻塞在尝试在通道 c 上发送值的行中。由于没有人从该通道接收数据,并且该通道没有缓冲,因此该 goroutine 永远不会前进,因此所有 2 个 goroutine 将永远阻塞。

请注意,defer wg.done() 应该是 goroutine 中的第一个语句。如果是最后一个,defer 不会有任何区别。

如果通道的缓冲区至少为 1,则可以继续发送操作:

c := make(chan int, 1)

输出将是(在 Go Playground 上尝试):

10

如果我们让通道不缓冲,则必须有另一个 goroutine 从通道接收数据,例如:

wg.add(1)
go func() {
    defer wg.done()
    x := <-c
    fmt.println("received:", x)
}()

然后输出将是(在 Go Playground 上尝试):

10
Received: 10

今天关于《问题:当使用例程和通道结合时可能会发生死锁》的内容就介绍到这里了,是不是学起来一目了然!想要了解更多关于的内容请关注golang学习网公众号!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>