首頁 > 後端開發 > Golang > 為什麼我的 Goroutine 遞增變數會產生意外結果?

為什麼我的 Goroutine 遞增變數會產生意外結果?

Mary-Kate Olsen
發布: 2024-10-29 20:38:29
原創
757 人瀏覽過

Why Does My Goroutine Incrementing a Variable Produce Unexpected Results?

這是編譯器最佳化的結果嗎?

在此程式碼片段中,啟動了一個 goroutine 並重複遞增變數 i:

<code class="go">package main

import "time"

func main() {
    i := 1
    go func() {
        for {
            i++
        }
    }()
    <-time.After(1 * time.Second)
    println(i)
}</code>
登入後複製

但是,輸出總是 1。這種行為可以歸因於 Go 記憶體模型和此程式碼的具體實作。

Go 記憶體模型

Go 記憶體模型定義了條件在這種情況下,可以保證在一個goroutine 中讀取變數時觀察到在不同goroutine 中寫入同一變數所產生的值。它強調了同步對於並發存取共享資料的重要性。

省略同步

在給定的程式碼中:

  • 對i 的賦值(即i )後面沒有任何同步事件,表示變更可能不會立即對其他goroutine 可見。
  • 編譯器可以透過將其簡化為無操作來最佳化此循環最佳化。

編譯器優化

激進的編譯器可能會刪除i 語句,有效地將goroutine 縮減為:

<code class="go">for {}</code>
登入後複製

同步示例

為了證明問題源自於缺乏同步,請考慮以下程式碼:

<code class="go">package main

import (
    "sync"
    "time"
)

func main() {
    mx := new(sync.Mutex)
    i := 1
    go func() {
        for {
            mx.Lock()
            i++
            mx.Unlock()
        }
    }()
    <-time.After(1 * time.Second)
    mx.Lock()
    println(i)
    mx.Unlock()
}</code>
登入後複製

在這種情況下,輸出不再是1,而是一個很大的數字,正如預期的那樣。 sync.Mutex 提供同步並確保兩個 goroutine 以受控方式存取 i,允許 goroutine 遞增 i 並使變更對主例程可見。

以上是為什麼我的 Goroutine 遞增變數會產生意外結果?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板