成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

Java的Volatile實(shí)例用法及講解

在原子性、可見性、有序性中,volatile關(guān)鍵字主要在可見性中發(fā)揮作用。

成都創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),鼓樓企業(yè)網(wǎng)站建設(shè),鼓樓品牌網(wǎng)站建設(shè),網(wǎng)站定制,鼓樓網(wǎng)站建設(shè)報價,網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,鼓樓網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競爭力。可充分滿足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時我們時刻保持專業(yè)、時尚、前沿,時刻以成就客戶成長自我,堅持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。

volatile聲明的變量對所有線程來說是可見的,就是說當(dāng)變量的值發(fā)生改變的時候,其他線程可以立馬發(fā)現(xiàn)這個變化。

public class Main {
  private static boolean isRuning;
  private static int number;

  private static class ReaderThread extends Thread {
    public void run() {
      while (!isRuning) {
        System.out.println(number);
      }
    }
  }

  public static void main(String[] args) throws InterruptedException {
    new ReaderThread().start();
    Thread.sleep(1000);
    number = 42;
    isRuning = true;
    Thread.sleep(1000);
  }
}

應(yīng)該是由于編譯器優(yōu)化的存在,這里變量雖然沒有被volatile修飾,但是仍然對其他線程可見。。。。。

那為啥Volatile修飾的變量i++卻會有并發(fā)問題呢?

因為i++并不是原子操作,

i++是有兩步操作的,比如 i=0; i++

1.讀取i=0

2.計算i+1,然后賦值給i

那么可能存在2個線程同時讀取到i=0,并計算出結(jié)果i=1然后賦值給I

那么就得不到預(yù)期結(jié)果i=2。

就是說雖然Volatile修飾的變量的變化可以被其他線程看到,但是如果同時去讀這個變量,然后進(jìn)行寫操作,則仍會導(dǎo)致線程安全問題。

更底層的原因是什么呢?

首先要知道Volatile修飾的變量會做兩件事(由lock指令完成):

  • 1)將當(dāng)前處理器緩存行的數(shù)據(jù)寫回到系統(tǒng)內(nèi)存。
  • 2)寫回內(nèi)存的操作會使在其他 CPU 里緩存了該內(nèi)存地址的額數(shù)據(jù)無效。

其他緩存會失效,不正好可以保證Volatile的原子性嗎?

然而并不是,

比如有T1 T2兩個線程進(jìn)行i++操作。

當(dāng)T1將變量加載到緩存,但是還沒進(jìn)行i++運(yùn)算,T2呢已經(jīng)加載完緩存并且已經(jīng)執(zhí)行完運(yùn)算,那這個時候T1緩存里的值就該變成無效的了。

但是Volatile并不是讓其他線程緩存無效以后就去重新加載主內(nèi)存中的值,如果這時候T2緩存的值已經(jīng)被放到寄存器并且cpu進(jìn)行計算了,那即使緩存無效也不會影響T2將計算的值回寫到主內(nèi)存中。

關(guān)于cpu執(zhí)行指令的過程可以參考https://blog.csdn.net/jizhu4873/article/details/84393905

當(dāng)一個變量定義為 volatile 之后,將具備兩種特性:

1.保證此變量對所有的線程的可見性,這里的“可見性”,如本文開頭所述,當(dāng)一個線程修改了這個變量的值,volatile 保證了新值能立即同步到主內(nèi)存,以及每次使用前立即從主內(nèi)存刷新。但普通變量做不到這點(diǎn),普通變量的值在線程間傳遞均需要通過主內(nèi)存(詳見:Java內(nèi)存模型)來完成。

2.禁止指令重排序優(yōu)化。有volatile修飾的變量,賦值后多執(zhí)行了一個“l(fā)oad addl $0x0, (%esp)”操作,這個操作相當(dāng)于一個內(nèi)存屏障(指令重排序時不能把后面的指令重排序到內(nèi)存屏障之前的位置),只有一個CPU訪問內(nèi)存時,并不需要內(nèi)存屏障;(什么是指令重排序:是指CPU采用了允許將多條指令不按程序規(guī)定的順序分開發(fā)送給各相應(yīng)電路單元處理)。

volatile 變量的內(nèi)存可見性是基于內(nèi)存屏障(Memory Barrier)實(shí)現(xiàn)。

內(nèi)存屏障則由lock指令實(shí)現(xiàn)

以上就是本次介紹的全部知識點(diǎn)內(nèi)容,感謝大家對創(chuàng)新互聯(lián)的支持。

當(dāng)前標(biāo)題:Java的Volatile實(shí)例用法及講解
轉(zhuǎn)載源于:http://jinyejixie.com/article40/pspeho.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供面包屑導(dǎo)航網(wǎng)站導(dǎo)航、定制網(wǎng)站、電子商務(wù)、微信公眾號、網(wǎng)站收錄

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)
漯河市| 苏尼特左旗| 泗水县| 沂水县| 封丘县| 女性| 枣阳市| 柳江县| 雅安市| 正宁县| 邵阳县| 定边县| 内江市| 右玉县| 台中市| 望江县| 中阳县| 温州市| 合阳县| 内乡县| 苗栗市| 吴忠市| 通化市| 龙海市| 平罗县| 双江| 河源市| 洛隆县| 赤水市| 河曲县| 屏山县| 尼木县| 长沙县| 高青县| 应用必备| 高雄县| 高陵县| 河源市| 灵璧县| 响水县| 东乌珠穆沁旗|