詳解Golang并發(fā)操作中常見的死鎖情形
什么是死鎖,在Go的協(xié)程里面死鎖通常就是永久阻塞了,你拿著我的東西,要我先給你然后再給我,我拿著你的東西又讓你先給我,不然就不給你。我倆都這么想,這事就解決不了了。
第一種情形:無緩存能力的管道,自己寫完自己讀
先上代碼:
func main() {
ch := make(chan int, 0)
ch <- 666
x := <- ch
fmt.Println(x)
}
我們可以看到這是一個(gè)沒有緩存能力的管道,然后往里面寫666,然后就去管道里面讀。這樣肯定會(huì)出現(xiàn)問題啊!一個(gè)無緩存能力的管道,沒有人讀,你也寫不了,沒有人寫,你也讀不了,這正是一種死鎖!
fatal error: all goroutines are asleep - deadlock!
解決辦法很簡單,開辟兩條協(xié)程,一條協(xié)程寫,一條協(xié)程讀。
第二種情形:協(xié)程來晚了
func main() {
ch := make(chan int,0)
ch <- 666
go func() {
<- ch
}()
}
我們可以看到,這條協(xié)程開辟在將數(shù)字寫入到管道之后,因?yàn)闆]有人讀,管道就不能寫,然后寫入管道的操作就一直阻塞。這時(shí)候你就有疑惑了,不是開辟了一條協(xié)程在讀嗎?但是那條協(xié)程開辟在寫入管道之后,如果不能寫入管道,就開辟不了協(xié)程。
第三種情形:管道讀寫時(shí),相互要求對(duì)方先讀/寫
如果相互要求對(duì)方先讀/寫,自己再讀/寫,就會(huì)造成死鎖。
func main() {
chHusband := make(chan int,0)
chWife := make(chan int,0)
go func() {
select {
case <- chHusband:
chWife<-888
}
}()
select {
case <- chWife:
chHusband <- 888
}
}
先來看看老婆協(xié)程,chWife只要能讀出來,也就是老婆有錢,就給老公發(fā)個(gè)八百八十八的大紅包。
再看看老公的協(xié)程,一看不得了,咋啦?老公也說只要他有錢就給老婆包個(gè)八百八十八的大紅包。
兩個(gè)人都說自己沒錢,老公也給老婆發(fā)不了紅包,老婆也給老公發(fā)不了紅包,這就是死鎖!
第四種情形:讀寫鎖相互阻塞,形成隱形死鎖
先來看一看代碼:
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()
}
}
這兩條協(xié)程,如果第一條協(xié)程先搶到了只寫鎖,另一條協(xié)程就不能搶只讀鎖了,那么因?yàn)榱硗庖粭l協(xié)程沒有讀,所以第一條協(xié)程就寫不進(jìn)。
如果第二條協(xié)程先搶到了只讀鎖,另一條協(xié)程就不能搶只寫鎖了,那么因?yàn)榱硗庖粭l協(xié)程沒有寫,所以第二條協(xié)程就讀不到。
到此這篇關(guān)于詳解Golang并發(fā)操作中常見的死鎖情形的文章就介紹到這了,更多相關(guān)Golang 并發(fā)死鎖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
go語言interface接口繼承多態(tài)示例及定義解析
這篇文章主要為大家介紹了go語言interface接口繼承多態(tài)示例及定義解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-04-04
golang讀取http的body時(shí)遇到的坑及解決
這篇文章主要介紹了golang讀取http的body時(shí)遇到的坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03
goland配置自動(dòng)注釋的實(shí)現(xiàn)
本文主要介紹了goland配置自動(dòng)注釋的實(shí)現(xiàn),文中通過圖文示例介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-08-08
Golang程序漏洞檢測器govulncheck的安裝和使用
govulncheck 是一個(gè)命令行工具,可以幫助 Golang 開發(fā)者快速找到項(xiàng)目代碼和依賴的模塊中的安全漏洞,該工具可以分析源代碼和二進(jìn)制文件,識(shí)別代碼中對(duì)這些漏洞的任何直接或間接調(diào)用,本文就給大家介紹一下govulncheck安裝和使用,需要的朋友可以參考下2023-09-09
使用Go語言實(shí)現(xiàn)一個(gè)簡單的無界資源池
本文我們希望通過go語言實(shí)現(xiàn)一個(gè)簡單的資源池,而這個(gè)資源池的資源包括但不限于數(shù)據(jù)庫連接池,線程池,協(xié)程池,網(wǎng)絡(luò)連接池,只要這些資源實(shí)現(xiàn)我們指定的關(guān)閉方法,則都可以通過我們封裝的資源池進(jìn)行統(tǒng)一管理,文中通過代碼示例給大家介紹的非常詳細(xì),需要的朋友可以參考下2024-05-05
Go語言基礎(chǔ)函數(shù)包的使用學(xué)習(xí)
本文通過一個(gè)實(shí)現(xiàn)加減乘除運(yùn)算的小程序來介紹go函數(shù)的使用,以及使用函數(shù)的注意事項(xiàng),并引出了對(duì)包的了解和使用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05

