<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-67  評(píng)論-522  文章-0  trackbacks-0
        在Java并發(fā)編程里面,volatile是個(gè)很重要的概念,大象也來(lái)講講自己對(duì)它的理解。
        以前曾經(jīng)有段時(shí)間我一直沒(méi)搞明白volatile到底怎么用,它是怎樣實(shí)現(xiàn)的同步,而且對(duì)于volatile變量還有一些限制條件。任何技術(shù)在沒(méi)完全弄明白之前,至少在沒(méi)熟練掌握之前都不太敢放心大膽的用,大象想將自己對(duì)它的理解分享出來(lái),給需要的人一些幫助。
        volatile是輕量級(jí)的鎖,它只具備可見(jiàn)性,但沒(méi)有原子特性。用volatile聲明的變量,它的同步特性,簡(jiǎn)單來(lái)講就是對(duì)該變量的單個(gè)讀/寫(xiě)是同步的。這是什么意思呢?我還是以共享變量i為例,不過(guò)在i的前面加上了volatile修飾符。
        private volatile int i = 0;
        public int get() {
            return i;
        }
        public void set(int i) {
            this.i = i;
        }

        為了與傳統(tǒng)的getXXXsetXXX方法區(qū)別開(kāi)來(lái),我將方法名改成了上面這樣。對(duì)于getset方法,如果有多個(gè)線程同時(shí)訪問(wèn),volatile是可以保證i的原子性的,再簡(jiǎn)單點(diǎn)講,對(duì)于變量igetset方法是同步的。這是通過(guò)什么來(lái)保證的呢?是通過(guò)Java語(yǔ)言規(guī)范:如果一個(gè)字段被聲明為volatileJava內(nèi)存模型確保所有線程看到這個(gè)變量的值是一致的。
        看到這里,可能有的童鞋會(huì)想,既然volatile可以保證內(nèi)存可見(jiàn)性,那不就解決了淺談Java共享變量這篇文章里面講到的共享變量的并發(fā)問(wèn)題嗎?只要在i的前面加上volatile就可以解決同步問(wèn)題了,你確定?實(shí)踐是最好的辦法,動(dòng)手試下,看看結(jié)果如何。
        事實(shí)證明這個(gè)辦法行不通,為什么呢?原因出在i++上面,增量操作符++不是原子的。這個(gè)操作分解開(kāi)來(lái)看是先從堆內(nèi)存中獲得i值的副本放到緩存中,然后對(duì)副本值加1,最后再將副本值寫(xiě)回到堆內(nèi)存的變量i中。從這個(gè)過(guò)程我們可以看到,從堆內(nèi)存中獲得i(get方法)以及將值寫(xiě)回到i(set方法)這兩步都是同步的,但中間的就不能保證是同步的了。
        對(duì)于volatile修飾的變量,只保證了他的可見(jiàn)性,但不保證原子性。最常用的應(yīng)該是boolean類(lèi)型,它用來(lái)作為狀態(tài)標(biāo)志,因?yàn)樗挥?/span>truefalse兩個(gè)值,不會(huì)有非原子性的操作。當(dāng)然不是說(shuō)只能用在布爾類(lèi)型變量上面,其它的基本類(lèi)型和對(duì)象類(lèi)型都可以用。但一定需要小心謹(jǐn)慎的處理,以免掉進(jìn)并發(fā)陷阱而不知。比如volatile變量就不適合用于不變性條件這種情況,以上下限為例,lower必須小于upper,這就是一種不變性條件,你可以理解為這是一種規(guī)則限制。它們都只有setget方法,但在set方法里面加入了約束條件,這時(shí),volatile的可見(jiàn)性就不能保證并發(fā)時(shí),lowerupper之間的不變性條件(lower<upper)一定成立了。

        /*
         * volatile只保證lowerupper的最后寫(xiě)入一定會(huì)被其它讀取的線程看到
         * 但不能保證在lowerupper寫(xiě)入時(shí),另一個(gè)變量的值沒(méi)有發(fā)生變化
         */
        private volatile int lower;
        private volatile int upper;

        public int getLower() {
            return lower;
        }

        public int getUpper() {
            return upper;
        }

        public void setLower(int lower) {
            if (lower > upper)
                throw new IllegalArgumentException();
            this.lower = lower;
        }

        public void setUpper(int upper) {
            if (upper < lower)
                throw new IllegalArgumentException();
            this.upper = upper;
        }

        如果lowerupper的初始值為010,同一時(shí)刻,線程1調(diào)用setLower(8),線程2調(diào)用setUpper(2),執(zhí)行上完全沒(méi)問(wèn)題,但是現(xiàn)在的lowerupper的值就變?yōu)榱?/span>82這種無(wú)效的數(shù)據(jù)了,所以volatile只能確保可見(jiàn)性,不能確保原子性。
        所以在使用volatile變量時(shí),請(qǐng)考慮是否滿(mǎn)足下面這樣的要求:
            1、對(duì)變量的寫(xiě)入操作不依賴(lài)變量的當(dāng)前值(i++這種操作就不行)
            2、沒(méi)有用于其它變量的不變式條件中(lower<upper)
        到這里,我們已經(jīng)明白了:用volatile修飾的變量只具備可見(jiàn)性,那么它是怎么保證可見(jiàn)性的呢?
        現(xiàn)在大家用的電腦CPU基本上都是多核的,至少兩核,緩存也有很多級(jí)(L1L2L3)。代碼在JVM里面執(zhí)行的時(shí)候,JVM如果發(fā)現(xiàn)有CPU在處理volatile變量的寫(xiě)入操作,就會(huì)告訴該CPU將當(dāng)前緩存中的數(shù)據(jù)寫(xiě)回到堆內(nèi)存中,但這時(shí)其它CPU的緩存值還是舊的,再執(zhí)行操作就會(huì)有問(wèn)題,所以在處理器的內(nèi)部實(shí)現(xiàn)了緩存一致性協(xié)議,當(dāng)有緩存中的數(shù)據(jù)寫(xiě)回內(nèi)存時(shí)會(huì)引起其它CPU里這個(gè)volatile變量的緩存值無(wú)效,如果這時(shí)候其它CPU要想使用就必須到堆內(nèi)存中重新讀取該值,這樣就實(shí)現(xiàn)了volatile變量的可見(jiàn)性。我這樣講方便大家理解,實(shí)際的情況比這復(fù)雜的多。
        以上是大象關(guān)于volatile變量的一些淺薄見(jiàn)解,真的很淺,大象學(xué)藝不精,有什么不對(duì)的,還請(qǐng)各位指出來(lái)。謝謝!
        本文為菠蘿大象原創(chuàng),如要轉(zhuǎn)載請(qǐng)注明出處。http://m.tkk7.com/bolo
    posted on 2014-06-20 17:08 菠蘿大象 閱讀(5979) 評(píng)論(2)  編輯  收藏 所屬分類(lèi): Concurrency

    評(píng)論:
    # re: 淺談volatile變量的理解[未登錄](méi) 2014-06-22 21:20 | 星情
    比 ibm devloper works 上的那篇關(guān)于 volatitle 的文章更易于理解  回復(fù)  更多評(píng)論
      
    # re: 淺談volatile變量的理解 2014-07-18 19:58 | zhangchao
    簡(jiǎn)單來(lái)說(shuō),volatile就是告訴程序,該變量是易變的,不穩(wěn)定的,每次必須去主存讀取,而不要從自己的緩存中獲取副本。  回復(fù)  更多評(píng)論
      

    只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 亚洲人成影院午夜网站| 亚洲va在线va天堂va四虎| 亚洲精品国产日韩| 99视频在线免费看| 久久亚洲国产视频| 亚洲精品免费观看| 久久久久亚洲AV无码专区体验| 七色永久性tv网站免费看| 久久99国产亚洲精品观看| 最新黄色免费网站| 亚洲欧洲精品国产区| 一区二区无码免费视频网站| 亚洲成_人网站图片| 日韩毛片无码永久免费看| 亚洲AV无码专区国产乱码不卡| 性感美女视频免费网站午夜| 亚洲AV综合色区无码一二三区| 免费人成视频在线观看不卡| 一级毛片一级毛片免费毛片| 亚洲国产综合无码一区| 最近免费中文字幕MV在线视频3| 久久精品a亚洲国产v高清不卡| 一个人看的www在线观看免费| 亚洲成av人无码亚洲成av人| 日韩亚洲国产综合久久久| 三上悠亚在线观看免费| 91亚洲国产成人精品下载| 成全视频在线观看免费高清动漫视频下载 | 亚洲高清一区二区三区| 亚洲AⅤ优女AV综合久久久| 免费看黄的成人APP| 亚洲一区二区三区久久| 亚洲精品一级无码中文字幕| 精品视频一区二区三区免费| 亚洲av产在线精品亚洲第一站 | 最近免费中文字幕高清大全| 亚洲精品无码av片| 亚洲精品少妇30p| 一二三四影视在线看片免费 | 野花香高清在线观看视频播放免费| 亚洲第一网站免费视频|