Go語言無緩沖通道的并發行為:為什么運行結果會有兩種可能性?

Go語言無緩沖通道的并發行為:為什么運行結果會有兩種可能性?

go語言通道的并發行為及非阻塞特性詳解

本文深入探討一段Go語言代碼在使用無緩沖通道時的運行結果,并解釋其背后的并發編程原理。代碼利用Go語言通道特性,但在不同情況下展現出不同的行為,引發了關于通道阻塞、協程啟動時間等問題的討論。

代碼如下:

package main  import "fmt"  func main() {     chanint := make(chan int)     defer close(chanInt)     go func() {         for {             res, ok := <-chanInt             if !ok {                 break //通道關閉則退出循環             }             fmt.Println(res, ok)         }     }()     chanInt <- 1     chanInt <- 10 }

這段代碼創建了一個無緩沖通道chanInt,并啟動一個goroutine從該通道接收數據并打印。主goroutine向通道發送1和10。然而,運行結果存在兩種可能性:打印“1 true”和“10 true”,或僅打印“1 true”。這引發了以下疑問:

立即學習go語言免費學習筆記(深入)”;

  1. 無緩沖通道輸出結果存在兩種情況的原因:

無緩沖通道的特性是:發送操作阻塞,直到有goroutine接收數據;接收操作也阻塞,直到有goroutine發送數據。主goroutine依次發送1和10。子goroutine接收并打印。如果子goroutine接收1的速度足夠快,則在主goroutine發送10之前完成打印“1 true”,隨后接收10并打印“10 true”。但如果子goroutine接收1的速度較慢,在主goroutine發送10并結束前,子goroutine可能只來得及接收并打印1。這是因為主goroutine結束導致通道關閉,子goroutine的接收操作會收到通道關閉的信號(ok為false),從而停止運行。

  1. 有緩沖通道(chanInt := make(chan int, 2))無輸出的原因:

將通道改為容量為2的有緩沖通道后,主goroutine的發送操作不會阻塞,因為它有足夠空間容納兩個數值。主goroutine發送完1和10后就結束,而子goroutine可能尚未啟動或開始接收數據。這是因為協程的啟動需要時間。如果主goroutine結束速度遠快于子goroutine啟動速度,子goroutine將無法從已關閉的通道中接收數據,導致沒有任何輸出。

通過分析,我們了解到Go語言并發編程中,協程啟動時間、通道的阻塞/非阻塞特性以及主goroutine的結束時間共同決定最終輸出結果。這些因素的相互作用導致結果的不確定性。 為了確保子goroutine能夠處理所有發送的數據,應該在發送數據后添加等待機制,例如使用WaitGroup同步goroutine。

以上就是Go語言無緩沖通道的并發行為:

? 版權聲明
THE END
喜歡就支持一下吧
點贊9 分享