Java四種記憶體屏障詳解,LoadLoad、LoadStore、StoreLoad、StoreStore

Yfeil發表於2024-04-10

屏障作用:

  1. 可見性:當一條執行緒修改了一個變數的值,新值會立即被寫入主記憶體,同時其他執行緒讀取該變數時會從主記憶體中讀取最新值,而不是使用執行緒快取中的值。

  2. 有序性:編譯器和處理器可能會對指令進行重排以提高效能,但這種重排可能會導致其他執行緒看到不一致的狀態。變數的讀寫操作前後會插入特定的記憶體屏障,這些屏障會禁止指令重排,從而保證了操作的順序性。

屏障類別:

  1. LoadLoad(讀讀屏障):先執行屏障前的 ,後執行屏障後的
  2. LoadStore(讀寫屏障):先執行屏障前的 ,後執行屏障後的
  3. StoreLoad(寫讀屏障):先執行屏障前的 ,後執行屏障後的
  4. StoreStore(寫寫屏障):先執行屏障前的 ,後執行屏障後的

插入時機表:

屏障需求 第二個操作
第一個操作 普通讀 普通寫

volatile讀

獲取鎖

volatile寫

釋放鎖

普通讀 LoadStore
普通寫 StoreStore

volatile讀

獲取鎖

LoadLoad LoadStore LoadLoad LoadStore

volatile寫

釋放鎖

StoreLoad StoreStore

程式碼示例:

class X {
    int a, b;
    volatile int v, u;

    void f() {
        int i, j;

        i = a;     // load a
        j = b;     // load b
        i = v;     // load v
                   //    LoadLoad    - volatile讀 和 volatile讀 之間插入LoadLoad
        j = u;     // load u
                   //    LoadStore   - volatile讀 和 普通寫 之間插入LoadStore
        a = i;     // store a
        b = j;     // store b
                   //    StoreStore  - 普通寫 和 volatile寫 之間插入StoreStore
        v = i;     // store v
                   //    StoreStore  - volatile寫 和 volatile寫 之間插入StoreStore
        u = j;     // store u
                   //    StoreLoad   - volatile寫 和 volatile讀 之間插入StoreLoad
        i = u;     // load u
                   //    LoadLoad    - volatile讀 和 普通讀 之間插入LoadLoad
                   //    LoadStore   - volatile讀 和 普通寫 之間插入LoadStore
        j = b;     // load b
        a = i;     // store a
    }
}

相關文章