运行时是否保留一个有向图,表示哪个goroutine等待某个地方?如果是这样,你能指点我到源代码中的相关位置吗?
我没有在Go专业编码,但发现当我玩它时它有几个不错的功能。
答案 0 :(得分:3)
您可以检查Go源并轻松找到:它发生在this function中,在程序可能进入死锁状态的各个地方调用它。
相关部分是运行时获取开放OS线程的数量,并检查它们中有多少实际运行代码。还有一些检查,但基本上就是这样。无论何时运行阻塞操作(例如锁定互斥锁已被锁定在其他地方,或从空通道接收),调度程序将尝试使该线程执行另一个goroutine的工作。如果找不到,则进入空闲状态。
基本上,调度程序总是尝试查找等待运行的代码。如果找不到任何东西,那么这就是僵局。
这当然排除了运行time.Sleep
的goroutines的情况,虽然它们是“空闲”,但是有一个线程主动检查它们何时准备好运行。换句话说,他们不依赖程序的其他部分来开始再次“运行”(例如互斥体的情况)。
答案 1 :(得分:2)
简短:负责共享goroutine之间OS线程执行时间的运行时调度程序,意识到所有goroutine都在等待或等待其他goroutine并结束死锁。
想象一下goroutine A从互联网上获取页面的情况,通过频道C将其发送到goroutine B. Goroutine A在goroutine B发送到频道C之前无所事事,所以goroutine A正在等待goroutine A. Goroutine B被阻塞等待系统调用(HTTP请求)完成,因此goroutine B没有等待其他goroutines。现在,如果你插入任何使goroutine B等待其他goroutine的操作(比如从D频道接收),goroutine B将被置于睡眠状态,并且由于所有其他goroutine(只是goroutine A真的)已经睡着了,我们结束了死锁
长:阅读Go scheduler。