第一次見到這個錯誤拼苍,也是比較懵逼,如果自己搞不清這個問題為什么出現(xiàn)其實就是基本概念沒理解清楚调缨。下面我就說說這個問題疮鲫。
其實這個問題很簡單,就是根據(jù)字面就可以解釋弦叶,所有的 groutine 睡著了俊犯。說白了就是產(chǎn)生了死鎖,而且是所有的goruntine(用戶級別的)都發(fā)生了死鎖伤哺。如下代碼會報此錯誤
package main
import (
"fmt"
"sync"
"time"
)
var a = sync.Mutex{}
var b = sync.Mutex{}
func main() {
a.Lock()
go block()
time.Sleep(time.Second)
b.Lock()
fmt.Println("main")
}
func block() {
b.Lock()
a.Lock()
fmt.Println("block")
}
以上代碼燕侠,是兩個goruntine 死鎖者祖,相當(dāng)于兩個goruntine都在等待對方,因此就出錯了绢彤。但是如果單純的理解為死鎖也是不對的七问,因為在golang中不只死鎖會引起此問題,看如下例子
package main
import "fmt"
func main() {
package main
func main() {
var a = make(chan int)
a <- 1
_ = <-a
}
這個例子是不是很神奇茫舶,先給 a 發(fā)送一個1械巡,然后在接收就出問題了,這是為什么呢奇适?我想應(yīng)該很多沒遇到這個問題的時候是想不明白的坟比,這是因為 a <- 1 這個操作,是阻塞操作嚷往,就是說 遇到了 a<-1 代碼就不走了葛账,什么時候代碼往下走?必須等到a里面的消息被讀出去才會繼續(xù)走皮仁,這個就不是鎖引起的籍琳,所以單純的理解為鎖也是不對的。其實 alseep 才是最準(zhǔn)確的描述方法贷祈,泛指引起goroutine掛起而且永遠(yuǎn)不會被喚醒的情況趋急。
知道了產(chǎn)生錯誤的原因其實就很容易避免了,做法無非就是想清楚邏輯势誊,因為正確的邏輯是不會出現(xiàn)這種情況的呜达,出現(xiàn)了問題就根據(jù)報錯的地方,看一下就知道怎么回事了粟耻,前提是你理解了產(chǎn)生問題的原因