php小編香蕉在這里為大家介紹一種常見(jiàn)的問(wèn)題,即Goroutine過(guò)早進(jìn)入睡眠狀態(tài)。在Go語(yǔ)言中使用Goroutine并發(fā)執(zhí)行任務(wù)是非常高效的,但有時(shí)候我們會(huì)遇到這樣的情況,即Goroutine在執(zhí)行任務(wù)之前就進(jìn)入了睡眠狀態(tài),導(dǎo)致任務(wù)無(wú)法正常進(jìn)行。本文將詳細(xì)解釋這個(gè)問(wèn)題的原因,并提供解決方法,幫助大家更好地理解和使用Goroutine。
問(wèn)題內(nèi)容
代碼:
package main import ( "fmt" "time" ) func main() { link := make(chan bool) stop := make(chan bool) go a(link, stop) go b(link) <-stop } func a(link chan bool, stop chan bool) { for i := 0; i < 20; i++ { time.Sleep(1 * time.Second) link <- true } stop <- true } func b(link chan bool) { go func() { <-link fmt.Println("A") }() go func() { <-link fmt.Println("B") }() }
登錄后復(fù)制
這段代碼沒(méi)有做任何特別的事情,我只是想理解通道和 goroutine。但出了點(diǎn)問(wèn)題,協(xié)程在兩次循環(huán)和應(yīng)用程序崩潰后進(jìn)入休眠狀態(tài)。
讓我們分析一下它的作用 – 每隔一秒消息發(fā)送到 link
。函數(shù) b
在兩個(gè)地方接收它,因此調(diào)用了 print
a 和 b。所以基本上每一秒 a 和 b 都應(yīng)該出現(xiàn)在控制臺(tái)中。但由于我不知道的原因,它沒(méi)有發(fā)生,程序打印 a 和 b 一次,然后崩潰。
我可能對(duì)這個(gè)概念理解不夠(golang確實(shí)不直觀),所以我希望我能在這里得到答案。
解決方法
只有當(dāng)有 goroutine 從中接收數(shù)據(jù)時(shí),發(fā)送到無(wú)緩沖通道的通道才會(huì)成功。對(duì)于前兩次發(fā)送,有 goroutine 從 link
通道接收。但是它們收到一個(gè)值并終止,并且不再有任何 goroutine 從 link
接收,因此第三個(gè)發(fā)送到 link
的塊。由于沒(méi)有其他 goroutine 運(yùn)行,程序出現(xiàn)死鎖。