1. 程式人生 > >Java volatile 怎麼保證不被指令重排序優化

Java volatile 怎麼保證不被指令重排序優化

記憶體間互動操作

  • lock: 作用主記憶體
  • unlock: 作用主記憶體
  • read/load:這兩個操作順序執行,不能單獨出現;主記憶體的變數=>工作記憶體的變數
  • use: 作用工作記憶體,把工作記憶體變數傳給執行引擎
  • assign: 作用工作記憶體,把執行引擎收到的值賦給工作記憶體變數
  • store/write: 這兩個操作順序執行;不能單獨出現;工作記憶體的變數=>主記憶體的變數

通過主記憶體與工作記憶體互動來理解這些操作:

注意:

  • 不允許工作記憶體直接使用未初始化的變數

記憶體模型的3個特徵

  • 原子性
  • 有序性, 同一個執行緒內觀察是有序, 一個執行緒觀察另一個執行緒的操作是無序的
  • 可見性

重排序

如下程式碼,由於threadA對於threadB是無序的,對A重排序優化,②可能提前執行,這就導致threadB跳過④

ThreadA {
  do something   //①
  set flag = true//②
}

ThreadB {
  if(flag){      //③
    do something //④
  }
}

通過volatile,synchronized可以禁止重排序優化

happens-before(hb)

意義:記憶體模型通過hb原則併發操作過程中的有序性問題

actionA先行發生actionB,就是說A對B可見(A的結果在B執行時可見)

  • 執行緒啟動/終結規則
  • volatile規則, volatile變數寫操作hb後面讀操作
  • lock規則, unlock hb lock
  • Order規則, 執行緒內書寫前面的操作hb書寫後面的操作
  • 中斷規則, Thread.interrupt hb 被中斷程式檢測到的中斷事件的發生
  • 傳遞性

volatile禁止重排序原理

如下圖,1、2保證可見性,3禁止重排序

  • 1.A動作之前必關聯P、F動作
  • 2.B動作自後必然伴隨G、Q動作
  • 3.A優先於B,則P優先於Q(這個比較顯然);B優先於A,則Q優先於P

volatile

例如:執行緒B對變數flag=true同步優先於A執行緒使用

volatileflagtrue