在此程式碼片段中,啟動了一個 goroutine 並重複遞增變數 i:
package main
import "time"
func main() {
i := 1
go func() {
for {
i
}
}()
然而,輸出總是1。這種行為可以歸因於Go記憶體模型和這段程式碼的具體實作。
Go內存模型
The Go 內存模型定義了在一個 Goroutine 中讀取變量時可以保證觀察到在不同 Goroutine 中寫入同一變量所產生的值的條件。它強調了同步對於並發存取共享資料的重要性。
省略同步
在給定的程式碼中:
- 對i 的賦值(即i )後面沒有任何同步事件,表明更改可能不會立即對其他goroutine 可見。
- 編譯器可以透過將其簡化為無操作來最佳化此循環最佳化。
編譯器最佳化
激進的編譯器可能會刪除i 語句,從而有效地將goroutine 縮減為:
for {}
同步範例
為了證明問題源自於缺乏同步,請考慮以下程式碼:
package main
import (
"sync"
"time"
)
func main() {
mx := new(sync.Mutex)
i := 1
go func() {
for {
mx.Lock()
i
mx.Unlock()
}
}()
在這種情況下,輸出不再是 1,而是一個很大的數字,正如預期的那樣。 sync.Mutex 提供同步並確保兩個 goroutine 以受控方式存取 i,允許 goroutine 遞增 i 並使變更對主例程可見。
免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。
Copyright© 2022 湘ICP备2022001581号-3