【问题标题】:Why is my code in deadlock without closing the channel?为什么我的代码在没有关闭通道的情况下陷入僵局?
【发布时间】:2020-08-29 21:33:23
【问题描述】:

我正在尝试编写程序:

package main

import (
    "fmt"
    "sync"
)

func main() {
    n := 4
    resChan := make(chan []int, n)
    res := []int{}
    var wg sync.WaitGroup
    for i := 0; i < n; i++ {
        wg.Add(1)
        go func(i int) {
            defer wg.Done()
            resChan <- append(res, i)
        }(i)
    }
    wg.Wait()

    close(resChan) // code will deadlock without this
    for subRes := range resChan {
        res = append(res, subRes...)
    }
    fmt.Printf("%v", res)
}

我认为我有一个缓冲通道,因此对通道的写入不会阻塞。但是,我得到了:

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.main()
    /tmp/sandbox562058728/prog.go:23 +0x14c

有人能解释一下为什么代码会这样吗?

【问题讨论】:

    标签: go


    【解决方案1】:

    在通道关闭之前,测距通道不会退出 for 循环。

    【讨论】:

      【解决方案2】:

      如果通道没有关闭,循环将永远不知道何时停止迭代过程。

      范围循环无法从通道读取,因为它在写入过程中被锁定。另一方面,没有更多数据要通过通道发送。因此,通道在写入过程中被锁定,并且永远不会被解锁。然后它会导致死锁。

      Golang Tour 页面上写着这样的注释:

      注意:只有发送方应该关闭通道,接收方不能。在关闭的频道上发送会导致恐慌。

      另一个注意事项:频道不像文件;您通常不需要关闭它们。仅当必须告知接收器没有更多值时才需要关闭,例如终止范围循环。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-04-07
        • 1970-01-01
        • 1970-01-01
        • 2016-11-20
        • 1970-01-01
        • 1970-01-01
        • 2019-02-27
        相关资源
        最近更新 更多