我正在閱讀The Little Go Book。
第 76 頁演示了如何使用單個鎖進行死鎖:
var (
lock sync.Mutex
)
func main() {
go func() { lock.Lock() }()
time.Sleep(time.Millisecond * 10)
lock.Lock()
}
正如作者所解釋的那樣,運行它會導致死鎖。但是,我不明白的是為什么。
我把程式改成這樣:
var (
lock sync.Mutex
)
func main() {
go func() { lock.Lock() }()
lock.Lock()
}
我的期望是仍然會出現僵局。但事實并非如此。
有人可以向我解釋這里發生了什么嗎?
我能想到的唯一可以解釋這一點的情況如下(但這是猜測):
第一個例子
- 鎖是在第一個 goroutine 中獲取的
time.Sleep()確保獲得鎖的呼叫- 的
main函式嘗試獲取導致死鎖鎖 - 程式退出
第二個例子
- 鎖是在第一個 goroutine 中獲取的,但這需要一些時間(??)
- 由于沒有延遲,
main函式在 goroutine 之前獲取鎖 - 程式退出
uj5u.com熱心網友回復:
在第一個例子中,main 休眠足夠長的時間給子 goroutine 啟動和獲取鎖的機會。然后該 goroutine 將在不釋放鎖的情況下愉快地退出。
當 main 恢復其控制流時,共享互斥鎖被鎖定,因此下一次獲取它的嘗試將永遠阻塞。由于此時 main 是唯一存活的例程,因此永遠阻塞會導致死鎖。
在第二個示例中,沒有呼叫time.Sleep, main 會直接獲取鎖。這成功了,所以 main 繼續并退出。然后子 goroutine將永遠阻塞,但由于 main 已經退出,程式只是終止,沒有死鎖。
順便說一句,即使 main 沒有退出,只要至少有一個 goroutine 沒有阻塞,就不會出現死鎖。為此,time.Sleep它不是阻塞操作,它只是在指定的持續時間內暫停執行。
uj5u.com熱心網友回復:
go當所有 goroutines(包括主要)都處于睡眠狀態時顯示死鎖錯誤。
在你的第一個例子中,goroutine在他呼叫之后,內部被執行并終止mutex.Lock()。然后主 goroutine 嘗試再次鎖定,但它會asleep等待機會占用鎖。所以現在我們在程式中的所有 goroutines(主要的)都處于睡眠模式,這將導致死鎖錯誤!
理解這一點很重要,因為可能會發生死鎖,但如果仍有正在運行的 goroutine,它不會總是顯示錯誤。這主要是生產中會發生什么。只有當整個程式陷入死鎖時才會報錯。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/386934.html
上一篇:NFS服務固定埠——筑夢之路
