Go go中的死鎖

2021-10-01 23:16:57 字數 1744 閱讀 9454

go語言中的協程(goroutine)和通道(channel)提供非常好的處理併發的方式,基於協程(goroutine)和通道(channel)可以將併發中的資料簡單化。但用不好則會帶來許多問題,死鎖就是協程出現問題的一種表現形式。

那什麼是死鎖?按照我對go死鎖的理解,就是在程式中的**被阻塞了,執行不下去,導致程式報錯。

在go語言中,主要存在這幾種死鎖情況

package main

import

"fmt"

func

main()

對於無緩衝通道c,在主協程中將1賦值給了他,但並沒有在其他協程中被使用,導致程式被阻塞。

package main

import

"fmt"

func

main()

()}

雖然這裡建立了乙個匿名協程,使用並提取了無緩衝通道c裡面的值,但程式還是死鎖了,**始終停留在上面。

package main

import

"fmt"

func

main()

()c <-

1 fmt.

println

("i am free"

)}

這裡把建立子協程的時機提前了,在子協程中其實**是被阻塞的,但這並不影響主協程的執行,當無緩衝通道c被賦值,則會在子協程中列印協程c攜帶的值。

只要主協程不被阻塞,程式就不會出現死鎖,子協程被阻塞不會造成程式死鎖

package main

import

"fmt"

func

main()

()c2 <-

2 c1 <-

1 fmt.

println

("i am locked"

)}

這裡2被賦值給通道c2,於是到子協程中尋找c2,但在子協程中**阻塞在c1這,導致主協程在等待子協程執行通道c2的操作,子協程在等待主協程給通道c1賦值的操作,兩個協程互相等待,最終整個程式被阻塞,報死鎖。

package main

import

"fmt"

func

main()

()c1 <-

1 c2 <-

2 fmt.

println

("i am free"

)}

這裡調換了c1c2被賦值的順序,程式能順利執行。

package main

import

"fmt"

func

main()

fmt.

println

("i am locked"

)}

緩衝通道容量被遍歷完的時候相當成了無緩衝通道,而在主協程這就造成了**的阻塞,導致程式死鎖,這和第一種是差不多的情況。

GO go中的反射與傳值

go中的反射reflect提供了兩種型別,其中type可以用來獲取資料的型別,而value可以用來接收資料的值。go中的所有函式呼叫都是值傳遞,所以當我們使用如下方法獲取x的值時,reflect.valueof 會將傳入的引數轉換為reflect.valuel型別,再賦值給目標引數 var x fl...

Go Go中延遲語句defer的注意事項

defer語句在不對的位置出現 會出現錯誤 file,err os.open null defer file.close if err nil res,err http.get 不翻牆的情況下。是無法訪問滴 defer res.body.close if err nil 這倆個 就是會報錯 因為把d...

Go Go中延遲語句defer的注意事項

defer語句在不對的位置出現 會出現錯誤 不fq的情況下。是無法訪問滴 defer res.body.close if err nil 這倆個 就是會報錯 因為把defer放在err判斷前面了,當出現錯誤err判斷直接return時,會去呼叫defer 這個時候file和res都是空指標,呼叫會報...