var mu = sync.Mutex{}
func f2() {
mu.Lock()
fmt.Println("call f2...")
}
func main() {
go f2()
time.Sleep(time.Second * 2)
mu.Lock()
fmt.Println("get lock in main")
}
我们知道有四个条件具有死锁,一个是Wait For condition
,它要求至少有两种资源才能获得。但是这里只有一种资源。
所以这是一个死锁吗?
[您的代码中有一个互斥锁,该互斥锁已锁定在2个goroutine中:在main
goroutine中,而另一个在执行f2()
中。
如果f2()
越早锁定互斥锁,主goroutine将永远无法再次锁定它,因此这是一个死锁。并且由于您在启动main()
(作为goroutine)和锁定互斥锁之间在f2
中使用了2秒钟的睡眠,因此您将观察到此死锁像总是一样。
[请注意,如果计划将main
goroutine首先锁定互斥锁,则不会发生死锁,因为main()
函数可以继续运行,并且一旦返回,应用程序将终止(不等待f2()
完)。但同样,由于您插入了睡眠,您将可能永远不会得到此结果。
我使用了词组“总是喜欢”和“可能从不”],因为睡眠指令对于goroutine调度程序来说是一个很好的调度点,但它不是一个同步点。运行时将安排其他goroutine在goroutine处于睡眠状态时运行(为什么不这样做),但这不能保证。同步点可以为您提供保证(例如通道通信,锁定,sync.Once
等)。在The Go Memory Model中有详细说明。