首頁 > 後端開發 > Golang > 主體

Go 並發:為什麼我的程式在使用頻道時會列印出意外的輸出?

DDD
發布: 2024-10-28 16:16:17
原創
914 人瀏覽過

Go Concurrency: Why Does My Program Print Unexpected Output When Using Channels?

解決了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。

可能的執行順序:

  1. Main 建立兩個 goroutine 用於顯示和求和。
  2. 調度器運行 display首先,列印訊息並在通道發送上阻塞。
  3. 調度程式切換到 sum goroutine。
  4. Sum 計算並列印結果。
  5. 調度程序恢復顯示,向通道發送一個值。
  6. 主協程收到數值後退出。

確保程式只列印第一個結果,我們可以使用結果通道:

<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中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!