解決了Go 並發和通道混亂
在Go 中處理並發時,通道在goroutine 之間的通信中發揮關鍵作用。然而,它們的行為有時會導致混亂。
考慮以下 Go 程式:
<code class="go">package main import "fmt" func display(msg string, c chan bool) { fmt.Println("display first message:", msg) c <- true } func sum(c chan bool) { sum := 0 for i := 0; i < 10000000000; i++ { sum++ } fmt.Println(sum) c <- true } func main() { c := make(chan bool) go display("hello", c) go sum(c) <-c }</code>
程式的預期行為是列印“顯示第一則訊息:hello”,然後退出。然而,實際輸出包含sum 函數的結果:
display first message: hello 10000000000
解釋
主Goroutine 阻塞在該行上:
<code class="go"><-c</code>
這意味著主Goroutine 在從通道c 接收到值之前無法繼續執行。 display 和 sum 都向 c 發送一個真值,這會解除主 goroutine 的阻塞。然而,調度器可以選擇先運行哪個 goroutine。
可能的執行順序:
解
確保程式只列印第一個結果,我們可以使用結果通道:
<code class="go">func display(msg string, result chan string) { result <- msg }</code>
並將main函數改為:
<code class="go">func main() { result := make(chan string) go display("hello", result) fmt.Println(<-result) }</code>
以上是Go 並發:為什麼我的程式在使用頻道時會列印出意外的輸出?的詳細內容。更多資訊請關注PHP中文網其他相關文章!