Java volatile關鍵字的用法


volatile不能解決同步問題

如果想要理解volatile關鍵字的作用不得不先了解Java內存模型

 

摘抄一下來自百度百科的話

在本次線程內,當讀取一個變量時,為提高存取速度,編譯器優化時有時會先把變量讀取到一個寄存器中;以后再取變量值時,就直接從寄存器中取值;
當變量值在本線程里改變時,會同時把變量的新值copy到該寄存器中,以便保持一致
當變量在因別的線程等而改變了值,該寄存器的值不會相應改變,從而造成應用程序讀取的值和實際的變量值不一致
當該寄存器在因別的線程等而改變了值,原變量的值不會改變,從而造成應用程序讀取的值和實際的變量值不一致
 
Java多線程中每個線程有一個自己的工作內存,線程從主內存中copy到工作內存,進行修改等一系列操作,然后把工作內存修改后的值copy回主內存
如果恰好此時有另一個進程同時進行這個操作,會發現意想不到的結果,和數據庫中的臟讀很像
 
給變量加上了volatile后,線程將直接對主內存中的變量進行操作,也就保證了變量無論是誰來讀,誰來寫,都是一個值
 
更加深入了解volatile關鍵字
volatile關鍵字還實現了 內存屏障,阻止 指令重排序
 
先來介紹一下指令重排序是什么玩意
先來看一段代碼
public class PossibleReordering {
static int x = 0, y = 0;
static int a = 0, b = 0;

public static void main(String[] args) throws InterruptedException {
    Thread one = new Thread(new Runnable() {
        public void run() {
            a = 1;
            x = b;
        }
    });

    Thread other = new Thread(new Runnable() {
        public void run() {
            b = 1;
            y = a;
        }
    });
    one.start();other.start();
    one.join();other.join();
    System.out.println(“(” + x + “,” + y + “)”);
}

思考一下這段代碼,我們之前如果對指令重排序不了解,那么會輕易得出(x=0,y=1)或者(x=1,y=0)

但是試一下這段代碼會發現(x=0,y=0)也會出現

說明指令並不按順序執行,這個時候,為了確保程序如我們期望一樣不會出現這個奇怪的問題,我們需要施加內存屏障

告訴編譯器,不允許你指令重排序

ok,簡單講述了一下volatile關鍵字的作用,對比synchronized給對象加鎖,大家可以想像成volatile是給屬性加鎖,修改volatile修飾的變量會比普通變量慢一點,但是讀取效率是一樣的,要注意的

,volatile關鍵字只是保證了變量在內存的可見性,並不保證原子性

 

 
 
 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM