国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

解析java中volatile關鍵字

2019-11-26 14:40:54
字體:
來源:轉載
供稿:網友

在java多線程編程中經常volatile,有時候這個關鍵字和synchronized 或者lock經常有人混淆,具體解析如下:
在多線程的環境中會存在成員變量可見性問題: java的每個線程都存在一個線程棧的內存空間,該內存空間保存了該線程運行時的變量信息,當線程訪問某一個變量值的時候首先會根據這個變量的地址找到對象的堆內存或者是棧堆存(原生數據類型)中的具體的內容,然后把這個內同賦值一個副本保存在本線程的線程棧中,緊接著對這個變量的一切操作在線程完成退出之前都和堆棧內存中的變量內容是沒有關系的,操作的是自己線程棧中的副本。當操作完后會把操作完的結果寫回到主內存中。假如有兩個線程A和B,同事操作某一個變量x;A對x進行了加1操作,那么B獲取的副本可能是x加1后的結果,也可能是x;為了保證獲取內存中最新的數據變量 需要加上 volatile 關鍵字,這樣在每次對x進行操作的時候都會去檢查下線程棧中的變量的值是不是和住內存中變量的值一樣,如果不一樣會重新load。
eg:

public class ThreadSee { //t1線程會根據flag的值做對應的操作,主線程會更改t1的值  public static void main(String[] args) throws InterruptedException {     ThReadTest th= new ThReadTest();     Thread t1 = new Thread(th);     t1.start();     Thread.sleep(1000);     th.changeFlag();     Thread.sleep(2000);     System.out.println(th.getFlag());   }  }   class ThReadTest implements Runnable{    //線程訪問變量時會把其load到對應的線程棧中,每次操作時都要獲取內存中最新的數據   private volatile boolean stopflag;   @Override   public void run() {     int i=0;     while(!stopflag){       i++;       System.out.println("=="+Thread.currentThread().getName());     }     System.out.println("Thread finish:"+i);   }   public void changeFlag(){     this.stopflag=true;     System.out.println(Thread.currentThread().getName()+"***********");   }    public boolean getFlag(){     return stopflag;   } } 

上述代碼如果去掉volatile,會一直死循環執行下去。
但是volatile不能保證線程安全的同步
eg:

public class ThreadSave implements Runnable{   static ThreadSave sync = new ThreadSave();   static volatile int j=0;   //Lock lock =new ReentrantLock();   public void inscane(){     // lock.lock();     for(int i=0;i<10000000;i++){       j++;     }    //  lock.unlock();   }   @Override   public void run() {     inscane();   }   public static void main(String[] args) throws InterruptedException {     Thread t1 = new Thread(sync);     Thread t2 = new Thread(sync);     t1.start();     t2.start();     t1.join();     t2.join();     System.out.println(j);   } } 

根據上述代碼執行的結果不是預期20000000,
因為對于volatile修飾的變量,jvm虛擬機只是保證從主內存加載到線程工作內存的值是最新的。
例如假如線程1,線程2 在進行線程棧與主內存read,load 操作中,發現主內存中count的值都是5,那么都會加載這個最新的值
在線程1堆count進行修改之后,會write到主內存中,主內存中的count變量就會變為6;
線程2由于已經進行read,load操作,在進行運算之后,也會更新主內存count的變量值為6;
導致兩個線程及時用volatile關鍵字修改之后,還是會存在并發的情況。
綜上所述:
volatile只會保證線程去做一個檢查當前線程棧的變量值和主內存中數據值是否一樣的這么一個動作,只此而已。而lock或者是synchronized 會保證某一時刻只有單個線程進入該方法,從而確保其線程安全性。
所以在如果多個線程去修改一個volatile變量那么沒有實際的邏輯意義。如果一個線程去修改其他的線程依賴修改的變量值,此時是有作用的。

以上就是本文的全部內容,希望對大家的學習有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 光山县| 孟州市| 新闻| 荣成市| 乐都县| 临沂市| 恩施市| 虎林市| 富蕴县| 厦门市| 香格里拉县| 英德市| 蓬安县| 盘山县| 太康县| 巨野县| 新昌县| 辽宁省| 阿勒泰市| 景宁| 双江| 永福县| 高台县| 大邑县| 绍兴县| 庄河市| 聊城市| 永登县| 灵丘县| 宝应县| 大冶市| 治县。| 乐至县| 泰州市| 鄯善县| 沂南县| 霍山县| 辰溪县| 丰都县| 咸阳市| 姜堰市|