多線程學習:volatile關鍵字的作用

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關鍵字的性能地的多

發佈了27 篇原創文章 · 獲贊 22 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章