Java線程內存模型跟CPU緩存模型相似,是基於CPU緩存模型來創建的,Java線程內存模型是標準化的,屏蔽掉了底層不一樣計算機的區別。java
編寫代碼來分析編程
public class VolatileVisibilityTest { private static boolean initFlag = false; public static void main(String[] args) throws InterruptedException { new Thread(new Runnable() { @Override public void run() { System.out.println("等待數據準備.."); while (!initFlag){ } System.out.println("============數據準備完畢,執行程序邏輯"); } }).start(); Thread.sleep(2000); new Thread(new Runnable() { @Override public void run() { prepareData(); } }).start(); } public static void prepareData(){  System.out.println("數據準備中.."); initFlag = true; System.out.println("數據準備完畢!"); } }
執行程序,打印結果緩存
並未出現架構
============數據準備完畢,執行程序邏輯
這段結果併發
第一個線程給了initFlag爲false,第二個執行了prepareData()因此initFlag爲true,可是第一個線程中的flag仍是爲false。ide
若是給initFlag加個volatile
關鍵字:性能
public class VolatileVisibilityTest { private static volatile boolean initFlag = false; public static void main(String[] args) throws InterruptedException { new Thread(new Runnable() { @Override public void run() { System.out.println("等待數據準備.."); while (!initFlag){ } System.out.println("============數據準備完畢,執行程序邏輯"); } }).start(); Thread.sleep(2000); new Thread(new Runnable() { @Override public void run() { prepareData(); } }).start(); } public static void prepareData(){ System.out.println("數據準備中.."); initFlag = true; System.out.println("數據準備完畢!"); } }
執行程序,返回結果線程
整個過程以下code
總線枷鎖(性能過低)server
MESI緩存一致性協議
總線嗅探機制
能夠感知到數據的變化從而將本身緩存裏的數據失效。Volatile緩存可見性實現原理
Java程序彙編代碼查看
IDEA這樣設置
顯式出的結果,其中volatile修飾的彙編代碼以下:
0x000000000349eaff:
lock
add dword ptr [rsp],0h ;*putstatic initFlag
; - com.tugohost.concurrent.VolatileVisibilityTest::prepareData@9 (line 31)