【问题标题】:Deadlock issue when using routine with channel使用带有通道的例程时出现死锁问题
【发布时间】:2018-12-23 17:42:29
【问题描述】:

我在使用带有通道的 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!

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

【问题讨论】:

    标签: go concurrency channel goroutine


    【解决方案1】:

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

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

    如果通道至少有一个缓冲区,则发送操作可以继续:

    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
    

    【讨论】:

      猜你喜欢
      • 2019-04-05
      • 1970-01-01
      • 2019-05-04
      • 2014-06-06
      • 1970-01-01
      • 2020-12-24
      • 2015-08-28
      • 1970-01-01
      • 2023-04-09
      相关资源
      最近更新 更多