av手机免费在线观看,国产女人在线视频,国产xxxx免费,捆绑调教一二三区,97影院最新理论片,色之久久综合,国产精品日韩欧美一区二区三区

java語(yǔ)言

解析Java中volatile關(guān)鍵字

時(shí)間:2024-11-27 07:16:40 java語(yǔ)言 我要投稿
  • 相關(guān)推薦

解析Java中volatile關(guān)鍵字

  解析Java中volatile關(guān)鍵字

  在java多線程編程中經(jīng)常volatile,有時(shí)候這個(gè)關(guān)鍵字和synchronized 或者lock經(jīng)常有人混淆,具體解析如下:

  在多線程的環(huán)境中會(huì)存在成員變量可見(jiàn)性問(wèn)題: java的每個(gè)線程都存在一個(gè)線程棧的內(nèi)存空間,該內(nèi)存空間保存了該線程運(yùn)行時(shí)的變量信息,當(dāng)線程訪問(wèn)某一個(gè)變量值的時(shí)候首先會(huì)根據(jù)這個(gè)變量的地址找到對(duì)象的堆內(nèi)存或者是棧堆存(原生數(shù)據(jù)類型)中的具體的內(nèi)容,然后把這個(gè)內(nèi)同賦值一個(gè)副本保存在本線程的線程棧中,緊接著對(duì)這個(gè)變量的一切操作在線程完成退出之前都和堆棧內(nèi)存中的變量?jī)?nèi)容是沒(méi)有關(guān)系的,操作的是自己線程棧中的副本。當(dāng)操作完后會(huì)把操作完的結(jié)果寫(xiě)回到主內(nèi)存中。假如有兩個(gè)線程A和B,同事操作某一個(gè)變量x;A對(duì)x進(jìn)行了加1操作,那么B獲取的副本可能是x加1后的結(jié)果,也可能是x;為了保證獲取內(nèi)存中最新的數(shù)據(jù)變量 需要加上 volatile 關(guān)鍵字,這樣在每次對(duì)x進(jìn)行操作的時(shí)候都會(huì)去檢查下線程棧中的變量的值是不是和住內(nèi)存中變量的值一樣,如果不一樣會(huì)重新load。

  eg:

  public class ThreadSee { //t1線程會(huì)根據(jù)flag的值做對(duì)應(yīng)的操作,主線程會(huì)更改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{  //線程訪問(wèn)變量時(shí)會(huì)把其load到對(duì)應(yīng)的線程棧中,每次操作時(shí)都要獲取內(nèi)存中最新的數(shù)據(jù)  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,會(huì)一直死循環(huán)執(zhí)行下去。

  但是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);  } }

  根據(jù)上述代碼執(zhí)行的結(jié)果不是預(yù)期20000000,

  因?yàn)閷?duì)于volatile修飾的變量,jvm虛擬機(jī)只是保證從主內(nèi)存加載到線程工作內(nèi)存的值是最新的`。

  例如假如線程1,線程2 在進(jìn)行線程棧與主內(nèi)存read,load 操作中,發(fā)現(xiàn)主內(nèi)存中count的值都是5,那么都會(huì)加載這個(gè)最新的值

  在線程1堆count進(jìn)行修改之后,會(huì)write到主內(nèi)存中,主內(nèi)存中的count變量就會(huì)變?yōu)?;

  線程2由于已經(jīng)進(jìn)行read,load操作,在進(jìn)行運(yùn)算之后,也會(huì)更新主內(nèi)存count的變量值為6;

  導(dǎo)致兩個(gè)線程及時(shí)用volatile關(guān)鍵字修改之后,還是會(huì)存在并發(fā)的情況。

  綜上所述:

  volatile只會(huì)保證線程去做一個(gè)檢查當(dāng)前線程棧的變量值和主內(nèi)存中數(shù)據(jù)值是否一樣的這么一個(gè)動(dòng)作,只此而已。而lock或者是synchronized 會(huì)保證某一時(shí)刻只有單個(gè)線程進(jìn)入該方法,從而確保其線程安全性。

  所以在如果多個(gè)線程去修改一個(gè)volatile變量那么沒(méi)有實(shí)際的邏輯意義。如果一個(gè)線程去修改其他的線程依賴修改的變量值,此時(shí)是有作用的。

  以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助。

【解析Java中volatile關(guān)鍵字】相關(guān)文章:

Java中Finally關(guān)鍵字06-30

理解java中的關(guān)鍵字06-22

Java中synchronized關(guān)鍵字的用法07-23

C語(yǔ)言中volatile關(guān)鍵字分析07-26

C語(yǔ)言中關(guān)鍵字volatile的含義07-22

java之this關(guān)鍵字用法事例解析10-11

Java中final關(guān)鍵字用法的講解10-13

Java編程中this關(guān)鍵字與super關(guān)鍵字的使用方法08-23

Java中的JDBC事務(wù)解析10-01