一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - 解析java中volatile關鍵字

解析java中volatile關鍵字

2020-03-22 12:55石頭_ly JAVA教程

這篇文章主要為大家解析了java中volatile關鍵字,經常有人把volatile關鍵字和synchronized或者lock混淆,本文就為大家好好區分,感興趣的小伙伴們可以參考一下

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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變量那么沒有實際的邏輯意義。如果一個線程去修改其他的線程依賴修改的變量值,此時是有作用的。

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

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 亚洲人成网站在线观看妞妞网 | 99久热只有精品视频免费观看17 | 俄罗斯图书馆无打码久久 | 免费观看国产大片资源视频 | 日韩成人av在线 | 男人操美女逼视频 | 桃乃木香奈作品在线观看 | 星空无限传媒视频在线观看视频 | 高清国语自产拍免费视频国产 | 4455永久在线观免费看片 | 亚洲邪恶天堂影院在线观看 | 欧美日韩亚洲高清不卡一区二区三区 | 国产精彩视频 | 99一区二区三区 | 日韩ab| 波多野结衣xxxxx在线播放 | 无人区1免费完整观看 | 日韩毛片免费线上观看 | www.俺去啦| 情趣内衣在线观看 | 2022最新国产在线 | 国产videos hd| 深夜日韩 | 欧美老人与小伙子性生交 | 青青青久在线视频免费观看 | 91精品综合久久久久m3u8 | 日韩激情视频在线观看 | 国产香蕉97碰碰久久人人 | 美琪美腿白丝交小说 | 男人女人插 | 午夜伦午夜伦锂电影 | 欧美视频久久 | 亚洲国产99在线精品一区69堂 | 男人狂躁女人gif动态图 | 午夜在线播放免费人成无 | 506rr亚洲欧美 | 激情综 | 亚洲品质自拍视频网站 | 国产伦码精品一区二区三区 | 久久人妻少妇嫩草AV无码 | 亚洲国产精品一区二区首页 |