Golang背后的算法是什么?所有goroutines都睡着了 - 死锁!`错误?

时间:2018-05-13 17:24:02

标签: go deadlock

运行时是否保留一个有向图,表示哪个goroutine等待某个地方?如果是这样,你能指点我到源代码中的相关位置吗?

我没有在Go专业编码,但发现当我玩它时它有几个不错的功能。

2 个答案:

答案 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