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關鍵字只是保證了變量在內存的可見性,並不保證原子性
