volatile關鍵字在於保證了線程可見性,線程的可見性涉及到Java虛擬機內存模型,用以下例子進行說明:
public class Volatile {
/*volatile*/ static boolean running = true;
public static void threadMethod() {
//4.主線程執行完畢後線程開始執行打印 start thread
System.out.println("start thread");
//5.這時正常情況下running應該爲false 並且不進入死循環
while (running) {
}
//6.並且最後打印end thread
System.out.println("end thread");
}
//當啓動main方法後
public static void main(String[] args) {
//1.首先會創建線程並調用threadMethod方法
new Thread(Volatile::threadMethod).start();
//2.然後睡眠1秒
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
//3.將running 設置爲false
running = false;
}
}
正常情況下應該如上方的註釋的順序進行執行,但是運行結果卻如下所示:
start thread
並沒有打印end thread,這就涉及到了JMM(Java虛擬機內存模型),在Java虛擬機中運行線程時,涉及到主內存和CPU運行緩衝區,以以上例子做說明,當我們啓動線程後讀取到的running 的值首先是ture,此時CPU會將該值加載到CPU的線程緩衝區當中,而當運行running = false 後主內存中的值已經發生改變,但是由於running 的值原本是ture從而導致while 循環一直是死循環,但是由於CPU一直忙於while 循環,一直沒有空閒時間從主內存中重新進行獲取數據導致了CPU緩衝區中的數據一直是ture,從而導致了線程一直無法執行完畢,而volatile關鍵字在於保證了線程的可見性,當running 發生改變時,將會通知線程數據發生了改變,而線程將從主內存中重新加載數據,並執行,當去掉volatile關鍵字的註釋後運行正常如下所示:
start thread
end thread
volatile關鍵字保證了線程可見性但是不保證線程原子性,而synchronized關鍵字既保證了線程的可見性又保證了線程的原子性,但是synchronized關鍵字的性能比volatile關鍵字的性能地的多