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

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

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

    posts - 310, comments - 6939, trackbacks - 0, articles - 3
      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理
    Think in Java 4th--Java中的volatile

    我們知道,在Java中設(shè)置變量值的操作,除了long和double類型的變量外都是原子操作,也就是說(shuō),對(duì)于變量值的簡(jiǎn)單讀寫操作沒(méi)有必要進(jìn)行同步。

    這在JVM 1.2之前,Java的內(nèi)存模型實(shí)現(xiàn)總是從主存讀取變量,是不需要進(jìn)行特別的注意的。而隨著JVM的成熟和優(yōu)化,現(xiàn)在在多線程環(huán)境下volatile關(guān)鍵字的使用變得非常重要。

    在當(dāng)前的Java內(nèi)存模型下,線程可以把變量保存在本地內(nèi)存(比如機(jī)器的寄存器)中,而不是直接在主存中進(jìn)行讀寫。這就可能造成一個(gè)線程在主存中修改了一個(gè)變量的值,而另外一個(gè)線程還繼續(xù)使用它在寄存器中的變量值的拷貝,造成數(shù)據(jù)的不一致。

    要解決這個(gè)問(wèn)題,只需要像在本程序中的這樣,把該變量聲明為volatile(不穩(wěn)定的)即可,這就指示JVM,這個(gè)變量是不穩(wěn)定的,每次使用它都到主存中進(jìn)行讀取。一般說(shuō)來(lái),多任務(wù)環(huán)境下各任務(wù)間共享的標(biāo)志都應(yīng)該加volatile修飾。

    Volatile修飾的成員變量在每次被線程訪問(wèn)時(shí),都強(qiáng)迫從共享內(nèi)存中重讀該成員變量的值。而且,當(dāng)成員變量發(fā)生變化時(shí),強(qiáng)迫線程將變化值回寫到共享內(nèi)存。這樣在任何時(shí)刻,兩個(gè)不同的線程總是看到某個(gè)成員變量的同一個(gè)值。 

    Java語(yǔ)言規(guī)范中指出:為了獲得最佳速度,允許線程保存共享成員變量的私有拷貝,而且只當(dāng)線程進(jìn)入或者離開(kāi)同步代碼塊時(shí)才與共享成員變量的原始值對(duì)比。 

    這樣當(dāng)多個(gè)線程同時(shí)與某個(gè)對(duì)象交互時(shí),就必須要注意到要讓線程及時(shí)的得到共享成員變量的變化。 

    而volatile關(guān)鍵字就是提示VM:對(duì)于這個(gè)成員變量不能保存它的私有拷貝,而應(yīng)直接與共享成員變量交互。 

    使用建議:在兩個(gè)或者更多的線程訪問(wèn)的成員變量上使用volatile。當(dāng)要訪問(wèn)的變量已在synchronized代碼塊中,或者為常量時(shí),不必使用。 

    由于使用volatile屏蔽掉了VM中必要的代碼優(yōu)化,所以在效率上比較低,因此一定在必要時(shí)才使用此關(guān)鍵字。

    請(qǐng)看如下示例:

     

     1package ch17_concurrency;
     2
     3
     4class UnresponsiveUI{
     5 private volatile double d=1;
     6 public UnresponsiveUI() throws Exception{
     7  while(d>0){
     8   d=d+(Math.PI+Math.E)/d;
     9  }

    10  System.in.read();
    11 }

    12}

    13
    14public class _19_ResponsiveUI extends Thread {
    15 private static volatile double d=1;
    16 public _19_ResponsiveUI(){
    17  setDaemon(true);
    18  start();
    19 }

    20 public void run(){
    21  while(true){
    22   //System.out.println(d);
    23   d=d+(Math.PI+Math.E)/d;
    24  }

    25 }

    26
    27 public static void main(String[] args) throws Exception {
    28  // TODO Auto-generated method stub
    29  //new UnresponsiveUI();
    30  new _19_ResponsiveUI();
    31  System.in.read();
    32  System.out.println(d);
    33 }

    34
    35}

    36

    評(píng)論

    # re: Think in Java 4th--Java中的volatile  回復(fù)  更多評(píng)論   

    2007-09-11 16:48 by dennis
    volatile需要強(qiáng)調(diào)的一點(diǎn)就是,它僅僅保證多線程環(huán)境下的可見(jiàn)性,不保證操作的原子性,舉的例子不大恰當(dāng)吧,想更多了解還是看看這個(gè)帖子

    http://www.javaeye.com/topic/109150

    # re: Think in Java 4th--Java中的volatile[未登錄](méi)  回復(fù)  更多評(píng)論   

    2008-05-23 14:26 by dd
    簡(jiǎn)單點(diǎn)就是線程在運(yùn)行的時(shí)候?yàn)榱颂岣咝仕员辉试S偷一點(diǎn)點(diǎn)懶,即忽視多線程的可能,不更新主存中的原本(線程使用的值是副本)。

    VOLATILE即告訴JVM,不能偷懶!

    這個(gè)特性應(yīng)該是從C移植過(guò)來(lái)的。而C是沒(méi)有線程的,所以說(shuō),JAVA的線程其實(shí)做得很勉強(qiáng)。

    因?yàn)閺恼Z(yǔ)義的角度講,線程的這種偷懶工作方式應(yīng)該是不被允許的。JVM首先應(yīng)該保證正確性(主存跟工作區(qū)的同步),然后再考慮性能優(yōu)化。不正確的東西,性能再好也是白搭。



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


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 免费永久在线观看黄网站| 精品亚洲456在线播放| 日本久久久免费高清| 最近免费mv在线电影| 2022国内精品免费福利视频| 亚洲人成未满十八禁网站| 精品无码一区二区三区亚洲桃色| 亚洲精品一级无码中文字幕| 午夜男人一级毛片免费| 在线观看成人免费视频不卡| 久久一本岛在免费线观看2020| 天堂亚洲免费视频| 美女隐私免费视频看| 久久经典免费视频| 无码日韩精品一区二区三区免费| www成人免费观看网站| 色屁屁在线观看视频免费| 亚洲日本VA午夜在线电影| 亚洲国产精品线观看不卡| 亚洲另类激情综合偷自拍| 亚洲av无码专区国产乱码在线观看| 久久精品亚洲福利| 亚洲精品亚洲人成在线观看下载| 亚洲国产成人久久综合野外| 一本色道久久88亚洲综合| 国产福利免费在线观看| 日本免费一二区在线电影| 全免费a级毛片免费**视频| 四虎成人免费影院网址| 成人免费视频一区| 三年片在线观看免费观看高清电影| 91香蕉成人免费网站| 午夜性色一区二区三区免费不卡视频 | 亚洲一区二区三区91| 亚洲另类自拍丝袜第1页| 亚洲成a人不卡在线观看| 亚洲成aⅴ人在线观看| 亚洲一区二区三区在线网站| 亚洲性线免费观看视频成熟| 亚洲熟女综合一区二区三区 | 国产精品二区三区免费播放心|