Go Lang 中的不正確同步
Go 記憶體模型規定,在單一goroutine 中,讀取和寫入的行為必須像在程序指定的順序。然而,當使用多個goroutine 時,會出現一種奇怪的行為,如以下程式碼所示:
var a, b int func f() { a = 1 b = 2 } func g() { print(b) print(a) } func main() { go f() g() }
根據文檔,程式碼有可能先列印“2”,然後列印“0”,而不是預期的“1”和“2”。為什麼會發生這種情況?
儘管在程式碼中看起來是連續的,但在 f goroutine 中對 a 和 b 的賦值可能會亂序。由於 Goroutine 不會使用賦值後的變量,因此編譯器可以透過重新排序來最佳化。
但是 f 和 g goroutine 之間缺乏同步,表示編譯器無法確保列印時的一致性。因此,當兩個賦值發生在同一個 goroutine 時,b 的值可以先於 a 被觀察到。
為了確保正確性,goroutine 之間需要同步。在同步點,編譯器將保證兩個賦值都已完成。例如,如果在列印呼叫之前放置同步點,則新值(2 和 1)將被正確列印,從而防止錯誤行為。
以上是為什麼 Go 的記憶體模型允許並發 Goroutine 中出現意外輸出?的詳細內容。更多資訊請關注PHP中文網其他相關文章!