程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> java volatile關鍵字的含義詳細引見

java volatile關鍵字的含義詳細引見

編輯:關於JAVA

java volatile關鍵字的含義詳細引見。本站提示廣大學習愛好者:(java volatile關鍵字的含義詳細引見)文章只能為提供參考,不一定能成為您想要的結果。以下是java volatile關鍵字的含義詳細引見正文


java volatile關鍵字

在java線程並發處置中,有一個關鍵字volatile的運用目前存在很大的混雜,以為運用這個關鍵字,在停止多線程並發處置的時分就可以萬事大吉。

Java言語是支持多線程的,為理解決線程並發的問題,在言語外部引入了 同步塊 和 volatile 關鍵字機制。

synchronized 

同步塊大家都比擬熟習,經過 synchronized 關鍵字來完成,一切加上synchronized 和 塊語句,在多線程訪問的時分,同一時辰只能有一個線程可以用

synchronized 修飾的辦法 或許 代碼塊。 

volatile

用volatile修飾的變量,線程在每次運用變量的時分,都會讀取變量修正後的最的值。volatile很容易被誤用,用來停止原子性操作。

上面看一個例子,我們完成一個計數器,每次線程啟動的時分,會調用計數器inc辦法,對計數器停止加一

執行環境——jdk版本:jdk1.6.0_31 ,內存 :3G   cpu:x86 2.4G

public class Counter
 {
 
  public static int count
 = 0;
 
  public static void inc()
 {
 
    //這裡延遲1毫秒,使得後果分明
    try {
      Thread.sleep(1);
    }
catch (InterruptedException
 e) {
    }
 
    count++;
  }
 
  public static void main(String[]
 args) {
 
    //同時啟動1000個線程,去停止i++計算,看看實踐後果
 
    for (int i
 = 0;
 i < 1000;
 i++) {
      new Thread(new Runnable()
 {
        @Override
        public void run()
 {
          Counter.inc();
        }
      }).start();
    }
 
    //這裡每次運轉的值都有能夠不同,能夠為1000
    System.out.println("運轉後果:Counter.count=" +
 Counter.count);
  }
}

運轉後果:Counter.count=995

實踐運算後果每次能夠都不一樣,本機的後果為:運轉後果:Counter.count=995,可以看出,在多線程的環境下,Counter.count並沒有希冀後果是1000

很多人以為,這個是多線程並提問題,只需求在變量count之前加上volatile就可以防止這個問題,那我們在修正代碼看看,看看後果是不是契合我們的希冀

public class Counter
 {
 
  public volatile static int count
 = 0;
 
  public static void inc()
 {
 
    //這裡延遲1毫秒,使得後果分明
    try {
      Thread.sleep(1);
    }
catch (InterruptedException
 e) {
    }
 
    count++;
  }
 
  public static void main(String[]
 args) {
 
    //同時啟動1000個線程,去停止i++計算,看看實踐後果
 
    for (int i
 = 0;
 i < 1000;
 i++) {
      new Thread(new Runnable()
 {
        @Override
        public void run()
 {
          Counter.inc();
        }
      }).start();
    }
 
    //這裡每次運轉的值都有能夠不同,能夠為1000
    System.out.println("運轉後果:Counter.count=" +
 Counter.count);
  }
}

運轉後果:Counter.count=992

運轉後果還是沒有我們希冀的1000,上面我們剖析一下緣由 

在 java 渣滓回收整理一文中,描繪了jvm運轉時辰內存的分配。其中有一個內存區域是jvm虛擬機棧,每一個線程運轉時都有一個線程棧,

線程棧保管了線程運轉時分變量值信息。當線程訪問某一個對象時分值的時分,首先經過對象的援用找到對應在堆內存的變量的值,然後把堆內存

變量的詳細值load到線程本地內存中,樹立一個變量正本,之後線程就不再和對象在堆內存變量值有任何關系,而是直接修正正本變量的值,

在修正完之後的某一個時辰(線程加入之前),自動把線程變量正本的值回寫到對象在堆中變量。這樣在堆中的對象的值就發生變化了。上面一幅圖

描繪這寫交互

read and load 從主存復制變量到以後任務內存
use and assign  執行代碼,改動共享變量值 
store and write 用任務內存數據刷新主存相關內容

其中use and assign 可以屢次呈現

但是這一些操作並不是原子性,也就是 在read load之後,假如主內存count變量發作修正之後,線程任務內存中的值由於曾經加載,不會發生對應的變化,所以計算出來的後果會和預期不一樣

關於volatile修飾的變量,jvm虛擬機只是保證從主內存加載到線程任務內存的值是最新的

例如假設線程1,線程2 在停止read,load 操作中,發現主內存中count的值都是5,那麼都會加載這個最新的值

在線程1堆count停止修正之後,會write到主內存中,主內存中的count變量就會變為6

線程2由於曾經停止read,load操作,在停止運算之後,也會更新主內存count的變量值為6

招致兩個線程及時用volatile關鍵字修正之後,還是會存在並發的狀況。

感激閱讀,希望能協助到大家,謝謝大家對本站的支持!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved