首頁 >後端開發 >Golang >為什麼 Go 程式會在給定程式碼片段中的訊息之前列印計算總和,即使主 Goroutine 會阻塞直到從通道接收到訊號?

為什麼 Go 程式會在給定程式碼片段中的訊息之前列印計算總和,即使主 Goroutine 會阻塞直到從通道接收到訊號?

DDD
DDD原創
2024-10-29 21:49:29583瀏覽

Why does the Go program print the sum of the computation before the message in the given code snippet, even though the main goroutine blocks until a signal is received from the channel?

Go 並發和通道混亂

在 Go 中,並發允許使用 goroutine 並發執行多個任務。通道促進這些 goroutine 之間的通信。然而,理解並發性可能具有挑戰性,尤其是在處理通道時。

考慮以下程式碼片段:

<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>

在這段程式碼中,我們建立了兩個 goroutine:display 和 sum。 display goroutine 列印訊息,向通道發送訊號,然後等待回應。 sum goroutine 執行長時間計算,列印結果,並向通道發送訊號。在主 goroutine 中,我們會阻塞,直到從通道接收到訊號。

程式碼的預期輸出是:

display first message: hello

但是,我們觀察到程式列印了兩則訊息以及計算總和:

display first message: hello
10000000000

理解問題

問題的出現​​是由於goroutine 調度的不確定性。 Go 中的調度器在未被阻塞的 goroutine 之間自由選擇。在此範例中,調度程序可以在任何給定時間執行任何 goroutine。

一個可能的執行順序是:

  1. main 建立 goroutine。
  2. 調度器選擇display,列印訊息並等待回應。
  3. 調度器切換到sum,執行很久。
  4. 調度器切換回display,發送訊號.
  5. 調度程式切換到 main,列印訊號並退出。

在這種情況下,在顯示器發送訊號之前列印總和,導致意外的輸出。

為了確保程式只列印訊息並在計算總和之前退出,我們可以使用不同的方法:

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

    go display("hello", result)
    go sum(result)

    fmt.Println(<-result)
}</code>

在此修訂版本中,結果通道攜帶單一值,即來自顯示goroutine 的訊息。主 goroutine 現在會列印來自通道的值,確保它在退出之前收到訊息。

以上是為什麼 Go 程式會在給定程式碼片段中的訊息之前列印計算總和,即使主 Goroutine 會阻塞直到從通道接收到訊號?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

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