JVM層級的內存屏障:JSR內存屏障

JSR內存屏障:

  1. LoadLoad:對於這樣的語句Load1;LoadLoad;Load2,在Load2及後續的讀操作要讀取的數據被訪問前,保證Load1要讀取的數據被讀取完畢;
  2. StoreStore:對於這樣的語句Store1;StoreStore;Store2,在Store2及後續的寫操作執行前,保證Store1的寫入操作對其他處理器可見;
  3. LoadStore:對於這樣的語句Load1;LoadStore;Store2,在Store2及後續的寫入操作被刷出前,保證Load1要讀取的數據被讀取完畢;
  4. StoreLoad:對於這樣的語句Store1;StoreLoad;Load2,在Load2及後續的讀操作要讀取的數據被訪問前,保證Store1的寫入操作對其他處理器可見;

  as-if-serial:不管如何重排序,單線程執行結果不會改變。在JVM層面volatile的實現細節特別保守,保證了內存可見性,並且成功防止指令重排序。如果是對對象加入volatile,是對該對象前後加入內存屏障,具體的實現細節如下所示:

StoreStoreBarrier
volatile 寫操作
StoreLoadBarrier

LoadLoadBarrier
volatile 讀操作
LoadStoreBarrier

happens-before原則:

  happens-before原則是Java內存模型中定義的兩個操作之間的偏序關係。比如說操作A先行發生於操作B,那麼在B操作發生之前,A操作產生的“影響”都會被操作B感知到。這裏的影響是指修改了內存中的共享變量、發送了消息、調用了方法等。

  1. 程序順序規則: 一個線程中的每個操作,happens-before於該線程中的任意後續操作;
  2. 監視器鎖規則: 對每一個鎖的解鎖,happens-before於隨後對該鎖的加鎖;
  3. Volatile變量規則:對一個volatile域的寫,happens-before於任意後續對這個volatile域的讀;
  4. 線程啓動規則:Thread的start()方法先行發生於這個線程的每一個操作;
  5. 線程終止原則:線程的所有操作都先行於此線程的終止檢測,可以通過Thread.join()方法結束、Thread.isAlive()的返回值等手段檢測線程的終止;
  6. 線程中斷原則:對線程interrupt()方法的調用先行發生於被中斷線程的代碼檢測到中斷事件的發生,可以通過Thread.interrupt方法檢測線程是否中斷;
  7. 對象終結規則:一個對象的初始化完成先於發生它的finalize()方法的開始;
  8. 傳遞性: 如果A happens-before B, B happens-before C, 那麼A happens-before C;

volatile關鍵字修飾變量的特殊規則:

  1. 可見性:對一個volatile變量的讀,總是能看到(任意線程)對這個volatile變量最後的寫入。
  2. 原子性:對任意單個volatile變量的讀/寫具有原子性,但類似於volatile++這種複合操作不具有原子性。

final域的重排序規則:

  1. 在構造函數內對一個final域的寫入,與隨後把這個被構造對象的引用賦值給一個引用變量,這兩個操作之間不能重排序;
  2. 初次讀一個包含final域的對象的引用,與隨後初次讀這個final域,這兩個操作之間不能重排序;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章