Golang Memory Model

TODO:

建議

如何保證在一個 goroutine 中看到在另一個 goroutine 修改的變數的值,如果程序中修改數據時有其他 goroutine 同時讀取, 那麼必須將讀取串行化。 為了串行化訪問,請使用 channel 或其他同步原語,例如 sync 和 sync/atomic 來保護數據

先行發生 (Happen Before)

在一個gouroutine中,讀和寫一定是按照程序中的順序執行的。 即編譯器和處理器只有在不會改變這個goroutine的行為時才可能修改讀和寫的執行順序。 由於重排,不同的goroutine可能會看到不同的執行順序。 例如: 一個goroutine執行 a=1; b=2, 另一個 goroutine 可能看到 b 在 a 之前更新。

var a, b int

func f() {
    a = 1
    b = 2
}

func g() {
    print(b)
    print(a)
}

func main() {
    go f()
    g()
}

it can happen that g prints 2 and then 0.

happens-before有什麼用呢?它可以用來幫助我們釐清兩個並發讀寫之間的關係。 對於並發讀寫問題,我們最關心的經常是reader是否能準確觀察到writer寫入的值。 happens-before正是為這個問題設計的,具體來說,要想讓某次讀取r準確觀察到某次寫入w,只需滿足:

  1. w happens-before r;
  2. 對變量的其它寫入w1,要麼 w1 happens-before w,要麼 r happens-before w1;簡單理解就是沒有其它寫入覆蓋這次寫入;

The happens before relation is defined as the transitive closure of the union of the sequenced before and synchronized before relations. Requirement 3: For an ordinary (non-synchronizing) data read r on a memory location x, W(r) must be a write w that is visible to r, where visible means that both of the following hold:

  1. w happens before r.
  2. w does not happen before any other write w' (to x) that happens before r.

Memory Rordering and Memory Barrier

https://cch123.github.io/ooo/

原子值複製

一旦atomic.Value類型的值,就是原子值被真正使用,它就不應該再被複製了。 只要用它來存儲值了,就相當於開始真正使用了。 atomic.Value類型屬於結構體類型,而結構體類型屬於值類型。 所以,複製該類型的值會產生一個完全分離的新值。這個新值相當於被複製的那個值的一個快照。 之後,不論後者存儲的值怎樣改變,都不會影響到前者的使用,反之亦然。 https://go.dev/play/p/Wua238yxLoJ

func main() {
    var box atomic.Value
    box2 := box  // 原子值真正使用之前可以被複製
    v1 := [...]int{1,2,3}
    box.Store(v1)  // 對box1的改變,不會影響到box2
    fmt.Println(box.Load())  // [1 2 3]
    fmt.Println(box2.Load()) // nil
}

Reference

© Kimi Tsai all right reserved.            Updated : 2023-07-12 09:04:53

results matching ""

    No results matching ""

    results matching ""

      No results matching ""