go - 为什么这个 Go 程序会挂起?

标签 go concurrency deadlock

我正在设置一个由三个 goroutine 组成的链,每个 goroutine 都有一个输入和一个输出 channel 。 goroutines 将从输入 channel 读取直到它关闭,增加值,将它发送到输出 channel 。但是,下面的程序会因以下输出而死锁:

goroutine 'one': 1
goroutine 'two': 2
goroutine 'three': 3
goroutine 'one': 10
goroutine 'two': 11
goroutine 'one': 100
fatal error: all goroutines are asleep - deadlock!

代码:

package main

import (
  "fmt"
)

func int_channel(id string, i chan int, o chan int) {
  defer close(o)

  for x := range i {
    fmt.Printf("goroutine '%s': %d\n", id, x)
    o <- x + 1
  }

  fmt.Println("done")
}

func main() {
  c0 := make(chan int)
  c1 := make(chan int)
  c2 := make(chan int)
  c3 := make(chan int)

  go int_channel("one", c0, c1)
  go int_channel("two", c1, c2)
  go int_channel("three", c2, c3)

  c0 <- 1
  c0 <- 10
  c0 <- 100
  c0 <- 1000
  c0 <- 10000
  c0 <- 100000
  close(c0)

  fmt.Println("Sent all numbers to c0")

  for x := range c3 {
    fmt.Printf("out: %d\n", x)
  }
}

最佳答案

它挂起是因为从未到达从输出 channel 读取的循环,因此 channel 没有“清空”,一旦每个 channel 都有一个值写入其中,就无法取得任何进展,程序挂起。要修复它,请写入另一个 goroutine 中的输入,即

func main() {
  c0 := make(chan int)
  c1 := make(chan int)
  c2 := make(chan int)
  c3 := make(chan int)

  go int_channel("one", c0, c1)
  go int_channel("two", c1, c2)
  go int_channel("three", c2, c3)

  go func(){
    c0 <- 1
    c0 <- 10
    c0 <- 100
    c0 <- 1000
    c0 <- 10000
    c0 <- 100000
    fmt.Println("Sent all numbers to c0")
    close(c0)
  }()


  for x := range c3 {
    fmt.Printf("out: %d\n", x)
  }
}

IOW,当行c0 <- 1被执行时,值流经所有三个 channel 并最终在 c3 中结束。 ,但由于尚未到达阅读器循环,它只是“坐在那儿”。然后行 c0 <- 10被执行,这个值最终在 c2 中因为不能写入c3 - 之前的值还在那里,阻止了写入。因此当行 c0 <- 100执行完毕,所有 channel 都已满,无法再进行下一步。

关于go - 为什么这个 Go 程序会挂起?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38159228/

相关文章:

json - 如何将JSON解析成数据结构

scala - Scala 中的进程级并行性

go - 如何全局定义结构并重用它的包

go - 在检查if-else条件时 undefined variable 名

concurrency - Erlang undef 错误

go - 为什么这会导致 Go 中的死锁?

php - PHP死锁异常代码,MySQL PDOException?

java - Java 中的死锁(附示例)

go - 处理用户回答

ajax - 处理数据库中的 AJAX 并发问题