日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
詳解Java中volatile關(guān)鍵字

volatile這個關(guān)鍵字可能很多朋友都聽說過,或許也都用過。在Java 5之前,它是一個備受爭議的關(guān)鍵字,因為在程序中使用它往往會導(dǎo)致出人意料的結(jié)果。在Java 5之后,volatile關(guān)鍵字才得以重獲生機。

創(chuàng)新互聯(lián)是專業(yè)的舒蘭網(wǎng)站建設(shè)公司,舒蘭接單;提供成都網(wǎng)站制作、網(wǎng)站設(shè)計、外貿(mào)網(wǎng)站建設(shè),網(wǎng)頁設(shè)計,網(wǎng)站設(shè)計,建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進行舒蘭網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團隊,希望更多企業(yè)前來合作!

volatile作用

volatile在并發(fā)編程中扮演著重要的角色,volatile是輕量級的synchronized,volatile關(guān)鍵字有兩個作用:

1)保證共享變量的可見性

可見性的意思是當一個線程修改一個共享變量時,另外一個線程能讀到這個修改的值。筆者此前一篇文章Java并發(fā)編程:Java內(nèi)存模型JMM中有說到,Java內(nèi)存模型中有主內(nèi)存和本地內(nèi)存之分,本地內(nèi)存持有共享變量的一份副本,線程對共享變量的修改是先修改本地內(nèi)存的副本,然后再回寫到主內(nèi)存中去。 可能存在這樣的情況,線程A和線程B同時去修改一個共享變量C,假設(shè)線程A先對共享變量C做了修改,而此時線程B卻沒能及時感知到共享變量C已經(jīng)發(fā)生了改變,緊接著B對本地過期的副本數(shù)據(jù)進行了修改,這造成了共享變量的不可見問題。

而使用了volatile關(guān)鍵字修改的共享變量,當線程修改了共享變量之后,會立馬刷新到主內(nèi)存中,并且會使其他線程緩存了該地址的數(shù)據(jù)失效,這就保證了線程之間共享變量的可見性。

2)防止指令重排序

volatile關(guān)鍵字的另外一個作用就是防止指令重排序。代碼在實際執(zhí)行過程中,并不全是按照編寫的順序進行執(zhí)行的,在保證單線程執(zhí)行結(jié)果不變的情況下,編譯器或者CPU可能會對指令進行重排序,以提高程序的執(zhí)行效率。但是在多線程的情況下,指令重排序可能會造成一些問題,最常見的就是雙重校驗鎖單例模式:

public class SingletonSafe {

  private static volatile SingletonSafe singleton;

  private SingletonSafe() {
 }

  public static SingletonSafe getSingleton() {
      if (singleton == null) {
          synchronized (SingletonSafe.class) {
              if (singleton == null) {
                  singleton = new SingletonSafe();
             }
         }
     }
      return singleton;
 }
}

如果沒有使用volatile關(guān)鍵字,則可能會出現(xiàn)其他線程獲取了一個未初始化完成的singleton對象,具體原因筆者不在這里贅述了,有興趣的同學(xué)可以搜索一下“double checked locking with delay initialization”學(xué)習(xí)下,筆者后續(xù)有時間再寫篇文章分析下。

volatile實現(xiàn)原理

1)可見性實現(xiàn)原理

對于volatile關(guān)鍵字修飾的變量,當對volatile變量進行寫操作的時候,JVM會向處理器發(fā)送一條lock前綴的指令,將這個緩存中的變量回寫到系統(tǒng)主存中。但是就算寫回到內(nèi)存,如果其他處理器緩存的值還是舊的,再執(zhí)行計算操作就會有問題,所以在多處理器下,為了保證各個處理器的緩存是一致的,就會實現(xiàn)緩存一致性協(xié)議。

緩存一致性協(xié)議:每個處理器通過嗅探在總線上傳播的數(shù)據(jù)來檢查自己緩存的值是不是過期了,當處理器發(fā)現(xiàn)自己緩存行對應(yīng)的內(nèi)存地址被修改,就會將當前處理器的緩存行設(shè)置成無效狀態(tài),當處理器要對這個數(shù)據(jù)進行修改操作的時候,會強制重新從系統(tǒng)內(nèi)存里把數(shù)據(jù)讀到處理器緩存里。

所以,如果一個變量被volatile所修飾的話,在每次數(shù)據(jù)變化之后,其值都會被強制刷入主存。而其他處理器的緩存由于遵守了緩存一致性協(xié)議,也會把這個變量的值從主存加載到自己的緩存中。這就保證了一個volatile在并發(fā)編程中,其值在多個緩存中是可見的。

2)防止指令重排序?qū)崿F(xiàn)原理

volatile防止指令重排序是通過內(nèi)存屏障來實現(xiàn)的。內(nèi)存屏障分為如下三種:

Store Barrier

Store屏障,是x86的”sfence“指令,強制所有在store屏障指令之前的store指令,都在該store屏障指令執(zhí)行之前被執(zhí)行。

Load Barrier

Load屏障,是x86上的”ifence“指令,強制所有在load屏障指令之后的load指令,都在該load屏障指令執(zhí)行之后被執(zhí)行

Full Barrier

Full屏障,是x86上的”mfence“指令,復(fù)合了load和save屏障的功能。 Java內(nèi)存模型中volatile變量在寫操作之后會插入一個store屏障,在讀操作之前會插入一個load屏障。一個類的final字段會在初始化后插入一個store屏障,來確保final字段在構(gòu)造函數(shù)初始化完成并可被使用時可見。也正是JMM在volatile變量讀寫前后都插入了內(nèi)存屏障指令,進而保證了指令的順序執(zhí)行。


文章題目:詳解Java中volatile關(guān)鍵字
當前鏈接:http://www.dlmjj.cn/article/dhesssj.html