以下golang代码死锁。有人可以帮助理解为什么吗?

时间:2014-10-04 04:03:25

标签: concurrency go

此示例取自http://blog.golang.org/pipelines。它运行并给出正确答案,但它显示以下运行时错误:"致命错误:所有goroutine都处于睡眠状态 - 死锁!"。任何人都可以帮助我理解为什么会这样吗?     包主要

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
}

1 个答案:

答案 0 :(得分:2)

for n := range in函数的sq()永不退出,并开始阻止(读取2个值后),因为gen()从未关闭其频道。
close(out)添加到go func的{​​{1}}会使其有效:see playground

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

gen()被屏蔽,这意味着sq()永远不会被调用,反过来close(out)会阻止main()(因为频道range sq()不是sq关闭)。

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