为什么会导致死锁?

时间:2019-08-22 15:29:04

标签: go channel

我不明白为什么以下代码会导致死锁...任何人都可以帮助我?

在什么情况下,通道将陷入僵局?我真的很困惑...

以下代码按此顺序打印字母和数字 “ 12AB34CD56EF78GH910IJ1112KL1314MN1516OP1718QR1920ST2122UV2324WX2526YZ2728” 我想使用渠道实现这一目标,但陷入僵局。 删除numberDone频道后,它会正常。

import (
    "fmt"
)

func main() {
    AlterPrint()
}

// POINT: communicate between goroutines by channel

func AlterPrint(){
  letter, number := make(chan bool), make(chan bool)
  letterDone := make(chan bool)
  numberDone := make(chan bool)
  go func() {
    i := 1
    for {
      if i > 28 {
          numberDone <- true
          return
      }
      select{
        case <-number: {
          fmt.Print(i)
          i++
          fmt.Print(i)
          i++
          letter <- true
          break
        }
        default: {
          break
        }
      }

    }
  }()

  go func(){
    i := 'A'
    for {
      if i > 'Z' {
        letterDone <- true
        return
      }
      select{
        case <-letter: {
          fmt.Print(string(i))
          i++
          fmt.Print(string(i))
          i++
          number <- true
          break
        }
        default: {
          break
        }
      }
    }
  }()
  number <- true
  <- letterDone
  <- numberDone
}```

I expect the output of "12AB34CD56EF78GH910IJ1112KL1314MN1516OP1718QR1920ST2122UV2324WX2526YZ2728", 
but the actual output is 
goroutine 1 [chan receive]:
main.AlterPrint()
    /tmp/54841538.go:66 +0x183
main.main()
    /tmp/54841538.go:7 +0x14

goroutine 5 [chan send]:
main.AlterPrint.func1(0xc82000c240, 0xc82000c180, 0xc82000c120)
    /tmp/54841538.go:31 +0x25a
created by main.AlterPrint
    /tmp/54841538.go:40 +0xde
exit status 2

1 个答案:

答案 0 :(得分:-1)

它应该实际打印您期望的内容,然后死锁。第二个goroutine完成所有操作,发送letterdone并终止。在这一点上,main开始等待编号为。第一个goroutine打印最后两个数字,并开始等待letter <-true。那是僵局,在这一点上什么也无法前进。 尝试使用fmt.Println而不是Print,可能是因为缓冲它无法打印所有内容。