1. volatile 關(guān)鍵字分析

        共 858字,需瀏覽 2分鐘

         ·

        2020-10-15 23:22

        點擊上方「藍字」關(guān)注我們

        一、volatile變量語義一的概念

          當一個變量被定義成volatile之后,具備兩個特性:

          特性一:保證此變量對所有線程的可見性。這里的“可見性”是指當一條線程修改了這個變量的值,新值對于其他線程來說是可以立即得知的。而普通變量并不能做到這一點,普通變量的值在線程傳遞時均需要通過主內(nèi)存來完成。比如:線程A修改了一個普通變量的值,然后向主內(nèi)存進行回寫,另一條線程B在線程A回寫完成了之后再對主內(nèi)存進行讀取操作,新變量值才會對線程B可見。

        二、volatile能夠保證線程安全嗎

          基于volatile變量在各個線程中是不存在一致性問題的,從物理存儲的角度看,各個線程的工作內(nèi)存中volatile變量也可以存在不一致的情況,但是由于每次使用前都要進行刷新,執(zhí)行引擎看不到不一致的情況,因此也可以人為不存在一致性問題,但是java里面的運算操作符并非是原子操作,這導致了volatile變量的運算在并發(fā)下一樣是不安全的。

        案例代碼:

        /**
        ?*?測試Volatile的特性
        ?*/

        public?class?VolatileTest?{
        public?static?volatile??int?race?=?0;

        public?static?void?increase(){
        ???? race++;
        }
        //定義線程的數(shù)量
        private?static?final?int?THREADS_COUNT?=?20;

        public?static?void?main(String[]?args)?{
        ???? Thread[]?threads?=?new?Thread[THREADS_COUNT];
        ???? for(int?i?=?0;i???????? threads[i]?=?new?Thread(new?Runnable()?{
        ???????????? @Override
        ??????????? ?public?void?run()?
        {
        ??????????????? for(int?j?=?0;j<1000;j++){
        ??????????????????? increase();
        ??????????????? }
        ???????????? }
        ???????? });
        ???????? threads[i].start();
        ???????? System.out.println("線程"+i+"開始執(zhí)行");
        ???? }

        ???? while?(Thread.activeCount()>2){
        ???????? System.out.println("Thread.activeCount()?=?"+Thread.activeCount());
        ???????? Thread.yield();//有其他線程等待時,將該線程設(shè)置為就緒狀態(tài)。
        ??? ?}
        ???? System.out.println("race:"+race);
        }
        }

          這段代碼發(fā)起了20個線程,每個線程都對race變量的做了10000次的自增操作,如果是正常的并發(fā)的話,那么race的結(jié)果用該是200000,可是執(zhí)行幾次,發(fā)現(xiàn)結(jié)果并不是200000,而都是一個小于200000的值。這是為什么呢?因為++操作本身就不是原子的,要經(jīng)過讀取計算和寫回,那么,我們通過一張圖模仿一下以上代碼:

          由于變量被volatile修飾,因此這張圖中的3,4操作是連續(xù)不間斷的,5,6,7的操作也是連續(xù)不間斷的,但是經(jīng)過兩個線程的讀取修改寫回操作后,i的值僅僅從1變?yōu)榱?,并不是我們想象的3,

        可能在這里理解上述的圖和描述有點抽象,因為有的朋友可能并不能理解數(shù)據(jù)在主存和緩存中的讀取更改的傳遞規(guī)則,在這里,補充一下變量在內(nèi)存之間的相互操作知識點,大家可以先看以下這塊內(nèi)容,再回過頭進行理解上述圖中的操作。

        三:內(nèi)存間的相互操作

        ·lock(鎖定):作用于主內(nèi)存的變量,它把一個變量標識為一條線程獨占的狀態(tài)。

        ·unlock(解鎖):作用于主內(nèi)存的變量,它把一個處于鎖定狀態(tài)的變量釋放出來,釋放后的變量才可以被其他線程鎖定。

        ·read(讀?。鹤饔糜谥鲀?nèi)存的變量,它把一個變量的值從主內(nèi)存?zhèn)鬏數(shù)骄€程的工作內(nèi)存中,以便隨后的load動作使用。

        ·load(載入):作用于工作內(nèi)存的變量,它把read操作從主內(nèi)存中得到的變量值放入工作內(nèi)存的變量副本中。

        ·use(使用):作用于工作內(nèi)存的變量,它把工作內(nèi)存中一個變量的值傳遞給執(zhí)行引擎,每當虛擬機遇到一個需要使用變量的值的字節(jié)碼指令時將會執(zhí)行這個操作。

        ·assign(賦值):作用于工作內(nèi)存的變量,它把一個從執(zhí)行引擎接收的值賦給工作內(nèi)存的變量,每當虛擬機遇到一個給變量賦值的字節(jié)碼指令時執(zhí)行這個操作。

        ·store(存儲):作用于工作內(nèi)存的變量,它把工作內(nèi)存中一個變量的值傳送到主內(nèi)存中,以便隨后的write操作使用。

        ·write(寫入):作用于主內(nèi)存的變量,它把store操作從工作內(nèi)存中得到的變量的值放入主內(nèi)存的變量中。

        ?   由volatile修飾的變量的特性保證此線程的可見性可知,當我們使用volatile修飾了一個變量后,一個線程對此變量的修改對于其他線程來講是立即可知的,也就是說.assign,.store,.write這三個操作是原子的,中間不會間斷,會馬上的同步主存,就像直接操作主存一樣,并通過緩存一致性通知其他的緩存中的副本過期。普通變量可能會在.assign,.store,.write這三個操作中插入其他的操作,導致更改后的數(shù)據(jù)不能立即同步回主存,這種情況在volatile修飾變量時是不存在的。

        四:使用volatile控制并發(fā)的場景

        由于volatile變量只能保證可見性,在不符合以下兩條規(guī)則的運算場景中,我們?nèi)匀灰ㄟ^加鎖(使用synchronized、java.util.concurrent中的鎖或原子類)來保證原子性:

        1、運算結(jié)果并不依賴變量的當前值,或者能夠確保只有單一的線程修改變量的值。

        2、變量不需要與其他的狀態(tài)變量共同參與不變約束。

        舉個例子:

        class?VolatileOne{
        volatile?boolean?isShutDown;

        public?void?shutDown(){
        ???? isShutDown?=?true;
        }


        public?void?dowork(){
        ???? while?(!isShutDown){
        ???????? //業(yè)務(wù)代碼
        ???? }
        }
        }

        這類場景就比較適合使用volatile控制并發(fā),當 shutDown()方法被調(diào)用時,能保證所有
        線程中執(zhí)行的dowork()方法都立即停下來。

        使用volatile變量的第二個特性是禁止指令重排優(yōu)化。

        掃碼二維碼

        獲取更多精彩

        Java樂園

        有用!分享+在看?
        瀏覽 64
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
          
          

            1. 国产精品久久久久久久三级 | 国产精品69毛片高清亚洲 | 18禁白丝袜美女网站色大片免费看 | 91成人短视频在线观看 | 天堂色区|