目錄
- 第一種情形:無緩存能力的管道,自己寫完自己讀
- 第二種情形:協程來晚了
- 第三種情形:管道讀寫時,相互要求對方先讀/寫
- 第四種情形:讀寫鎖相互阻塞,形成隱形死鎖
什么是死鎖,在Go的協程里面死鎖通常就是永久阻塞了,你拿著我的東西,要我先給你然后再給我,我拿著你的東西又讓你先給我,不然就不給你。我倆都這么想,這事就解決不了了。
第一種情形:無緩存能力的管道,自己寫完自己讀
先上代碼:
func main() {
ch := make(chan int, 0)
ch - 666
x := - ch
fmt.Println(x)
}
我們可以看到這是一個沒有緩存能力的管道,然后往里面寫666,然后就去管道里面讀。這樣肯定會出現問題?。∫粋€無緩存能力的管道,沒有人讀,你也寫不了,沒有人寫,你也讀不了,這正是一種死鎖!
fatal error: all goroutines are asleep - deadlock!
解決辦法很簡單,開辟兩條協程,一條協程寫,一條協程讀。
第二種情形:協程來晚了
func main() {
ch := make(chan int,0)
ch - 666
go func() {
- ch
}()
}
我們可以看到,這條協程開辟在將數字寫入到管道之后,因為沒有人讀,管道就不能寫,然后寫入管道的操作就一直阻塞。這時候你就有疑惑了,不是開辟了一條協程在讀嗎?但是那條協程開辟在寫入管道之后,如果不能寫入管道,就開辟不了協程。
第三種情形:管道讀寫時,相互要求對方先讀/寫
如果相互要求對方先讀/寫,自己再讀/寫,就會造成死鎖。
func main() {
chHusband := make(chan int,0)
chWife := make(chan int,0)
go func() {
select {
case - chHusband:
chWife-888
}
}()
select {
case - chWife:
chHusband - 888
}
}
先來看看老婆協程,chWife只要能讀出來,也就是老婆有錢,就給老公發個八百八十八的大紅包。
再看看老公的協程,一看不得了,咋啦?老公也說只要他有錢就給老婆包個八百八十八的大紅包。
兩個人都說自己沒錢,老公也給老婆發不了紅包,老婆也給老公發不了紅包,這就是死鎖!
第四種情形:讀寫鎖相互阻塞,形成隱形死鎖
先來看一看代碼:
func main() {
var rmw09 sync.RWMutex
ch := make(chan int,0)
go func() {
rmw09.Lock()
ch - 123
rmw09.Unlock()
}()
go func() {
rmw09.RLock()
x := - ch
fmt.Println("讀到",x)
rmw09.RUnlock()
}()
for {
runtime.GC()
}
}
這兩條協程,如果第一條協程先搶到了只寫鎖,另一條協程就不能搶只讀鎖了,那么因為另外一條協程沒有讀,所以第一條協程就寫不進。
如果第二條協程先搶到了只讀鎖,另一條協程就不能搶只寫鎖了,那么因為另外一條協程沒有寫,所以第二條協程就讀不到。
到此這篇關于詳解Golang并發操作中常見的死鎖情形的文章就介紹到這了,更多相關Golang 并發死鎖內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- Go 語言中的死鎖問題解決
- Go語言死鎖與goroutine泄露問題的解決
- golang coroutine 的等待與死鎖用法
- go select編譯期的優化處理邏輯使用場景分析
- Django實現jquery select2帶搜索的下拉框
- Go語言使用select{}阻塞main函數介紹
- matplotlib之多邊形選區(PolygonSelector)的使用
- golang中的select關鍵字用法總結
- Go select 死鎖的一個細節