【问题标题】:The following golang code deadlocks. Could someone help in understanding why?以下 golang 代码死锁。有人可以帮助理解为什么吗?
【发布时间】:2014-11-29 03:13:01
【问题描述】:

这个例子取自http://blog.golang.org/pipelines。它运行并给出正确答案,但显示以下运行时错误:“致命错误:所有 goroutines 都处于睡眠状态 - 死锁!”。谁能帮我理解为什么会这样? 主包

import (
    "fmt"
)

func gen(nums ...int) <- chan int {
    out := make(chan int)
    go func() {
        for _, n := range nums {
            out <- n
        }
    }()
    return out
}

func sq(in <- chan int) <- chan int {
    out := make(chan int)
    go func() {
        for n := range in {
            out <- n * n
        }
        close(out)
    }()
    return out
}

func main() {
    for n := range sq(gen(2,3)) {
        fmt.Println(n)
    }
}

但是下面的修改没有。

func main() {
    // Set up the pipeline.
    c := gen(2, 3)
    out := sq(c)

    // Consume the output.
    fmt.Println(<-out) // 4
    fmt.Println(<-out) // 9
}

【问题讨论】:

    标签: concurrency go


    【解决方案1】:

    sq() 函数的for n := range in 永远不会退出,并开始阻塞(在读取 2 个值后),因为gen() 从未关闭其通道。
    close(out) 添加到gen()go func 将使其工作:see playground

    使用通道,接收器会阻塞直到接收到值。
    The range keyword, when used with a channel, will wait on the channel until it is closed

    sq() 被阻塞,这意味着close(out) 永远不会被调用,而main() 又会阻塞range sq()(因为通道sq 没有关闭)。

    在您的第二个示例中,main() 本身退出,这意味着即使 sq() 被阻止,一切仍然停止。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-03
      • 2015-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      相关资源
      最近更新 更多