2 回答

TA貢獻1779條經驗 獲得超6個贊
您的main()函數嘗試在所有通道上發送,并且只有一次嘗試在單獨的并發 goroutine 中從這些通道中讀取。這是否成功取決于 goroutine 調度程序。如果非阻塞接收f2()比發送更早安排main(),那么后面的發送main()將永遠阻塞(沒有人會再次嘗試接收ch2)。
擺脫死鎖的一種方法是使用接收操作而不是非阻塞接收(在Go Playground上嘗試):
func f1() {
<-ch1
fmt.Println("ch1")
}
func f2() {
<-ch2
fmt.Println("ch2")
}
因此,無論何時main()在這些通道上發送值,總會有一個接收器準備好繼續,所以main()不會卡住。
請注意,當main()返回時,應用程序結束,它不會等待非主 goroutine 完成。因此,您可能無法在控制臺上看到ch1和打印。ch2有關詳細信息,請參閱Go 中的 goroutine 沒有輸出。
如果您的意圖是在您的應用程序存在之前等待所有 goroutine 完成它們的工作,請使用sync.WaitGroup它(在Go Playground上嘗試):
var ch1 = make(chan int)
var ch2 = make(chan int)
var wg sync.WaitGroup
func f1() {
defer wg.Done()
<-ch1
fmt.Println("ch1")
}
func f2() {
defer wg.Done()
<-ch2
fmt.Println("ch2")
}
func main() {
wg.Add(1)
go f1()
wg.Add(1)
go f2()
ch1 <- 1
ch2 <- 2
wg.Wait()
}
在此處查看更多示例:解決 goroutines 死鎖;并防止 main() 函數在 goroutine 在 Golang 中完成之前終止。
另一種選擇是為通道提供 1 的緩沖區,因此main()可以在沒有接收器準備好從通道接收的情況下在通道上發送 1 值(在Go Playground上試試這個):
var ch1 = make(chan int, 1)
var ch2 = make(chan int, 1)
有了這個,可以在沒有and的main()情況下繼續,所以再一次,不能保證你會看到任何打印出來的東西。f1()f2()

TA貢獻1784條經驗 獲得超7個贊
此處使用的通道是無緩沖通道。
當 main goroutines 啟動時,它會創建兩個新的 goroutine f1 和 f2。
當執行 f1 或 f2 時,它將檢查我們是否在通道中有值,否則它將打印默認消息并退出。
理想情況下,channels 會先發布值,然后通過 goroutine 接收
實際情況是 goroutine 通過打印默認情況退出,但主 goroutine 試圖在通道中發布值,但由于沒有接收器,它面臨死鎖情況。
從第一個示例中刪除了死鎖,請參考鏈接: https: //play.golang.org/p/6RuQQwC9JkA
但是,如果 main 例程退出,所有關聯的 goroutine 將被自動終止。這就是為什么我們可以看到該值是任意打印的。
從第二個示例中刪除了死鎖,請參閱鏈接: https: //play.golang.org/p/yUmc_jjZMgV
sync.WaitGroup 正在讓 main goroutine 等待,這就是為什么我們可以在每次程序執行時觀察輸出。
- 2 回答
- 0 關注
- 144 瀏覽
添加回答
舉報