dtz46697 2015-11-17 12:35
浏览 26
已采纳

为什么这会导致Go陷入僵局?

This is not a question about how to better write this. It's a question specifically about why Go is causing a deadlock in this scenario.

package main

import "fmt"

func main() {
    chan1 := make(chan bool)
    chan2 := make(chan bool)

    go func() {
        for {
            <-chan1
            fmt.Printf("chan1
")
            chan2 <- true
        }
    }()

    go func() {
        for {
            <-chan2
            fmt.Printf("chan2
")
            chan1 <- true
        }
    }()

    for {
        chan1 <- true
    }
}

Outputs:

chan1
chan2
chan1
chan2
chan1
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
goroutine 5 [chan send]:
goroutine 6 [chan send]:
exit status 2

Why does this not cause an infinite loop? How come it does two full "ping-pings" (instead of just one) before giving up?

  • 写回答

3条回答 默认 最新

  • doumo3903 2015-11-17 13:08
    关注

    From the runtime perspective you get a deadlock because all routines try to send onto a channel and there's no routine waiting to receive anything.

    But why is it happening? I will give you a story as I like visualising what my routines are doing when I encounter a deadlock.

    You have two players (routines) and one ball (true value). Every player waits for a ball and once they get it they pass it back to the other player (through a channel). This is what your two routines are really doing and this would indeed produce an infinite loop.

    The problem is the third player introduced in your main loop. He's hiding behind the second player and once he sees the first player has empty hands, he throws another ball at him. So we end up with both players holding a ball, couldn't pass it to another player because the other one has (the first) ball in his hands already. The hidden, evil player is also trying to pass yet another ball. Everyone is confused, because there're three balls, three players and no empty hands.

    In other words, you have introduced the third player who is breaking the game. He should be an arbiter passing the very first ball at the beginning of the game, watching it, but stop producing balls! It means, instead of having a loop in you main routine, there should be simply chan1 <- true (and some condition to wait, so we don't exit the program).

    If you enable logging in the loop of main routine, you will see the deadlock occurs always on the third iteration. The number of times the other routines are executed depends on the scheduler. Bringing back the story: first iteration is a kick-off of the first ball; next iteration is a mysterious second ball, but this can be handled. The third iteration is a deadlock – it brings to life the third ball which can't be handled by anybody.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 孟德尔随机化结果不一致
  • ¥15 深度学习残差模块模型
  • ¥50 怎么判断同步时序逻辑电路和异步时序逻辑电路
  • ¥15 差动电流二次谐波的含量Matlab计算
  • ¥15 Can/caned 总线错误问题,错误显示控制器要发1,结果总线检测到0
  • ¥15 C#如何调用串口数据
  • ¥15 MATLAB与单片机串口通信
  • ¥15 L76k模块的GPS的使用
  • ¥15 请帮我看一看数电项目如何设计
  • ¥23 (标签-bug|关键词-密码错误加密)