Deadlock满足条件
当多个协程共同工作时,每个协程手里都持有相同资源的一部分,又需要另外一部分资源来完成当前工作,相互等待对方持有的资源而有不肯释放自身的资源,就这样僵持下去谁也得不到需要的资源,也无法执行自身的任务,最终就形成了Deadlock。最著名的Deadlock就是哲学家进餐的故事,此时需要借助外部资源的动力打破这种僵局(破坏了Deadlock的条件),大家都可以愉快的干自己的事情了。
下面看一个deadlock示例:
package main
import "fmt"
func main() {
ch := make(chan bool)
ch <- true
fmt.Println(<-ch)
}
上述代码执行后,会报如下错误:
✗ go run demo/pp.go
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
/Users/houjie/Desktop/ccky/demo/pp.go:7 +0x37
exit status 2
之所以会报上述错误,是因为通过make(chan bool)
创建出来的ch
是nil
,对其读写操作均会导致当前协程阻塞。阻塞发生在main主协程里,此时有没有其他子协程可以执行,基本就可以确定这种僵局永远不会比打破,main协程就会主动出击把自己杀死,就会报fatal error: all goroutines are asleep - deadlock!
出来。
了解了Deadlock原因,下面对上面代码改造如下:
package main
import "fmt"
func main() {
ch := make(chan bool)
go func() {
ch <- true
}()
fmt.Println(<-ch)
}
将对ch
读写操作放到不同的协程里,就不会发生Deadlock了,因为写操作的阻塞分别放生在子协程和main主协程里,main主协程就会认为还有等下去的希望,黄天不负主协程,最终他等来了子协程写入的数据,成功读取了并打印出来。