首頁  >  文章  >  後端開發  >  為什麼我的 Go 代碼會列印 100 億個數字的總和,而不是僅僅「顯示第一則訊息:你好」?

為什麼我的 Go 代碼會列印 100 億個數字的總和,而不是僅僅「顯示第一則訊息:你好」?

DDD
DDD原創
2024-10-28 07:49:02149瀏覽

Why does my Go code print the sum of 10 billion numbers instead of just

Go 並發與通道混亂

問題

使用者正在嘗試理解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>

預期輸出僅為“顯示第一則訊息:你好”,因為主函數一旦從通道接收到資料就應該退出。然而,實際產出還包括 100 億個數字的總和。

答案

程式碼中的主要問題是調度器可以在兩個 goroutine 之間自由選擇(顯示和求和)未被阻止。雖然程式設計師期望顯示首先完成並在求和完成之前將資料發送到通道,但由於調度程序的不確定性,這種情況可能不會發生。

在一個可能的執行場景中:

  1. main 建立兩個 goroutine 來顯示和求和。
  2. 調度程式立即切換到顯示。
  3. 顯示列印其訊息並阻塞等待接收器接受發送到通道的資料.
  4. 調度程式運行 sum 而不是恢復顯示。
  5. sum 計算並列印 100 億個數字的總和。
  6. 排程器選擇在 sum 完成後恢復顯示。
  7. display 傳送資料到通道。
  8. 調度程式切換到 main 接收來自通道的資料。
  9. main 列印總和並退出程式。

為了解決這個問題並確保只列印「display first message: hello」訊息,一種方法是使用結果通道接收來自 display 的訊息並立即終止程式。修改後的 main 函數為:

<code class="go">func main() {
    result := make(chan string)

    go display("hello", result)
    fmt.Println(<-result)
}</code>

以上是為什麼我的 Go 代碼會列印 100 億個數字的總和,而不是僅僅「顯示第一則訊息:你好」?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn