成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

關(guān)于volatile的理解

LiveVideoStack / 818人閱讀

摘要:但在多線程環(huán)境中就可能出現(xiàn)問題如下面代碼線程語(yǔ)句語(yǔ)句線程線程中的語(yǔ)句和語(yǔ)句并沒有數(shù)據(jù)依賴關(guān)系,所以可能會(huì)進(jìn)行指令重排序,先去執(zhí)行語(yǔ)句,而這時(shí)線程會(huì)以為線程已經(jīng)執(zhí)行完而去執(zhí)行這樣就導(dǎo)致程序出錯(cuò)。

經(jīng)常會(huì)聽到volatile這個(gè)關(guān)鍵字,但沒有深入的去了解過它,今天好好的整理一下
要談volatile,我們先談?wù)勊睦洗蟾鐂ynchronized
一.synchronized

并發(fā)編程中最重要的三個(gè)特性是什么?原子性,可見性,有序性。只要有一個(gè)不能保證,就有可能導(dǎo)致程序的運(yùn)行錯(cuò)誤,我們熟知的synchronized就能保障原子性,可見性,有序性,因?yàn)閟ynchronized能保障任意一個(gè)時(shí)刻只有一個(gè)線程執(zhí)行該代碼塊,自然就不存在原子性的問題,又因?yàn)樵卺尫沛i之前會(huì)將變量的修改刷新到主存中,因此保證可見性,又因?yàn)槊恳粫r(shí)刻只有一個(gè)線程在執(zhí)行代碼,相當(dāng)于讓線程順序執(zhí)行同步代碼,所以也可以保證有序性。所以synchronized可保證原子性,可見性,有序性

二.volatile

volatile可以說是一個(gè)稍弱的同步機(jī)制,因?yàn)樗梢员U峡梢娦院陀行蛐?,不能保障原子?/p>

1.volatile可見性

先看下圖,java中所有的變量都存儲(chǔ)在主內(nèi)存區(qū),在多線程環(huán)境中,還有自己的工作內(nèi)存,線程操作變量時(shí)是從主存中拷貝變量到工作內(nèi)存操作,這樣很容易產(chǎn)生"臟讀"的問題。synchronized解決此問題的方法上面也談到了,volatile是如何保證的呢?當(dāng)一個(gè)變量被volatile修飾時(shí),它會(huì)保證每次被修改的值會(huì)被立刻更新到主存,而且當(dāng)緩存1對(duì)某個(gè)變量進(jìn)行修改時(shí),其它線程的工作內(nèi)存中的該變量的緩存行無效(反映到硬件層的話,就是CPU的L1或者L2緩存中對(duì)應(yīng)的緩存行無效),緩存2發(fā)現(xiàn)自己的變量無效后會(huì)等待緩存行對(duì)應(yīng)的主存地址被更新后從主存中讀取最新值,這樣就保證了可見性

2.volatile有序性

說到volatile的有序性就要提到指令重排序(Instruction Reorder),什么是指令重排序?這是JVM為了提高代碼的執(zhí)行效率對(duì)代碼進(jìn)行的優(yōu)化,它不能保證代碼先后順序執(zhí)行的一致,但可以保證執(zhí)行的結(jié)果和順序執(zhí)行的結(jié)構(gòu)一致。但在多線程環(huán)境中就可能出現(xiàn)問題,如下面代碼

        //線程1
        func1();               語(yǔ)句1
        boolean flag = true;   語(yǔ)句2

        //線程2
        while (!flag){
            sleep();
        }
        func2();

線程1中的語(yǔ)句1和語(yǔ)句2并沒有數(shù)據(jù)依賴關(guān)系,所以可能會(huì)進(jìn)行指令重排序,先去執(zhí)行語(yǔ)句2,而這時(shí)線程2會(huì)以為線程1已經(jīng)執(zhí)行完func1()而去執(zhí)行func2(),這樣就導(dǎo)致程序出錯(cuò)。
volatile關(guān)鍵字修飾的變量能禁止指令重排序,這樣就在一定程度上保證了有序性
應(yīng)用:

(1)狀態(tài)標(biāo)記量
        //線程1
        func1();                        語(yǔ)句1
        boolean volatile flag = true;   語(yǔ)句2

        //線程2
        while (!flag){
            sleep();
        }
        func2();
這是對(duì)上面程序的改進(jìn),避免了程序出錯(cuò)

(2)單例模式中的雙重校驗(yàn)鎖

public class Singleton3 {
    private Singleton3(){}
    private static volatile Singleton3 instance = null;

    public static Singleton3 getInstance() {
        if(instance == null){
            synchronized (Singleton3.class){
                instance = new Singleton3();
            }
        }
        return instance;
    }
}

我們看到已經(jīng)有synchronizd來保證線程同步,為什么還需要volatile來修飾變量instance呢?
原因在 instance = new Singleton3();這句,JVM實(shí)際上對(duì)它進(jìn)行了如下操作

(1)給instance分配內(nèi)存
(2)調(diào)用Singleton3的構(gòu)造函數(shù)完成初始化成員變量
(3)將instance指向內(nèi)存分配空間

但由于JVM存在指令重排序優(yōu)化,執(zhí)行的順序可能就為1-3-2,就可能發(fā)生當(dāng)3執(zhí)行完另一個(gè)線程以為它已經(jīng)執(zhí)行完了,搶占當(dāng)前線程,這時(shí)instance非null但沒有初始化,所以另一個(gè)線程和以后的線程都會(huì)直接返回該沒有初始化的instance,從而出現(xiàn)錯(cuò)誤。當(dāng)有volatile修飾變量instance,就可以禁止指令重排序,從而避免出錯(cuò)。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/69079.html

相關(guān)文章

  • 死磕 java同步系列之volatile解析

    摘要:前半句是指線程內(nèi)表現(xiàn)為串行的語(yǔ)義,后半句是指指令重排序現(xiàn)象和工作內(nèi)存和主內(nèi)存同步延遲現(xiàn)象。關(guān)于內(nèi)存模型的講解請(qǐng)參考死磕同步系列之。目前國(guó)內(nèi)市面上的關(guān)于內(nèi)存屏障的講解基本不會(huì)超過這三篇文章,包括相關(guān)書籍中的介紹。問題 (1)volatile是如何保證可見性的? (2)volatile是如何禁止重排序的? (3)volatile的實(shí)現(xiàn)原理? (4)volatile的缺陷? 簡(jiǎn)介 volatile...

    番茄西紅柿 評(píng)論0 收藏0
  • 死磕 java同步系列之volatile解析

    摘要:前半句是指線程內(nèi)表現(xiàn)為串行的語(yǔ)義,后半句是指指令重排序現(xiàn)象和工作內(nèi)存和主內(nèi)存同步延遲現(xiàn)象。關(guān)于內(nèi)存模型的講解請(qǐng)參考死磕同步系列之。目前國(guó)內(nèi)市面上的關(guān)于內(nèi)存屏障的講解基本不會(huì)超過這三篇文章,包括相關(guān)書籍中的介紹。問題 (1)volatile是如何保證可見性的? (2)volatile是如何禁止重排序的? (3)volatile的實(shí)現(xiàn)原理? (4)volatile的缺陷? 簡(jiǎn)介 volatile...

    番茄西紅柿 評(píng)論0 收藏0
  • 死磕 java同步系列之volatile解析

    摘要:前半句是指線程內(nèi)表現(xiàn)為串行的語(yǔ)義,后半句是指指令重排序現(xiàn)象和工作內(nèi)存和主內(nèi)存同步延遲現(xiàn)象。關(guān)于內(nèi)存模型的講解請(qǐng)參考死磕同步系列之。目前國(guó)內(nèi)市面上的關(guān)于內(nèi)存屏障的講解基本不會(huì)超過這三篇文章,包括相關(guān)書籍中的介紹。問題 (1)volatile是如何保證可見性的? (2)volatile是如何禁止重排序的? (3)volatile的實(shí)現(xiàn)原理? (4)volatile的缺陷? 簡(jiǎn)介 volatile...

    kviccn 評(píng)論0 收藏0
  • 理解java Volatile 關(guān)鍵字

    摘要:最近在看多線程相關(guān),看到這篇來自大神關(guān)于關(guān)鍵字的講解感覺非常詳細(xì)易懂,特此轉(zhuǎn)載一下。如果對(duì)增加聲明則所有線程對(duì)的寫都會(huì)立即刷新到主存中,而且所有對(duì)的讀也都直接從主存中去讀。 最近在看java多線程相關(guān),看到這篇來自大神Jakob Jenkov關(guān)于Volatile關(guān)鍵字的講解感覺非常詳細(xì)易懂,特此轉(zhuǎn)載一下。原文鏈接:http://tutorials.jenkov.com/j... 內(nèi)存可...

    ConardLi 評(píng)論0 收藏0
  • 關(guān)于ConcurrentHashMap1.8個(gè)人理解

    摘要:數(shù)據(jù)結(jié)構(gòu)重要成員變量代表整個(gè)哈希表??破眨鉀Q多線程并行情況下使用鎖造成性能損耗的一種機(jī)制,操作包含三個(gè)操作數(shù)內(nèi)存位置預(yù)期原值和新值。 ConcurrenHashMap 。下面分享一下我對(duì)ConcurrentHashMap 的理解,主要用于個(gè)人備忘。如果有不對(duì),請(qǐng)批評(píng)。 HashMap嚴(yán)重的勾起了我對(duì)HashMap家族的好奇心,下面分享一下我對(duì)ConcurrentHashMap 的理解...

    olle 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<