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

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

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

    posts - 431,  comments - 344,  trackbacks - 0

    最近看LumaQQ的源碼發(fā)現(xiàn)一個(gè)volatile(中文意思是“可變的、不穩(wěn)定的”),找了篇英文介紹。抽空我翻譯了一下,翻錯(cuò)了大家不要見笑。。。

    volatile關(guān)鍵字有什么用?
      恐怕比較一下volatile和synchronized的不同是最容易解釋清楚的。volatile是變量修飾符,而synchronized則作用于一段代碼或方法;看如下三句get代碼:

  • int i1;                          int geti1() {return i1;}
  • volatile int i2;              int geti2() {return i2;}
  • int i3; synchronized     int geti3() {return i3;}
  •   geti1()得到存儲(chǔ)在當(dāng)前線程中i1的數(shù)值。多個(gè)線程有多個(gè)i1變量拷貝,而且這些i1之間可以互不相同。換句話說(shuō),另一個(gè)線程可能已經(jīng)改變了它線程內(nèi)的i1值,而這個(gè)值可以和當(dāng)前線程中的i1值不相同。事實(shí)上,Java有個(gè)思想叫“主”內(nèi)存區(qū)域,這里存放了變量目前的“準(zhǔn)確值”。每個(gè)線程可以有它自己的變量拷貝,而這個(gè)變量拷貝值可以和“主”內(nèi)存區(qū)域里存放的不同。因此實(shí)際上存在一種可能:“主”內(nèi)存區(qū)域里的i1值是1,線程1里的i1值是2,線程2里的i1值是3——這在線程1和線程2都改變了它們各自的i1值,而且這個(gè)改變還沒(méi)來(lái)得及傳遞給“主”內(nèi)存區(qū)域或其他線程時(shí)就會(huì)發(fā)生。
      而geti2()得到的是“主”內(nèi)存區(qū)域的i2數(shù)值。用volatile修飾后的變量不允許有不同于“主”內(nèi)存區(qū)域的變量拷貝。換句話說(shuō),一個(gè)變量經(jīng)volatile修飾后在所有線程中必須是同步的;任何線程中改變了它的值,所有其他線程立即獲取到了相同的值。理所當(dāng)然的,volatile修飾的變量存取時(shí)比一般變量消耗的資源要多一點(diǎn),因?yàn)榫€程有它自己的變量拷貝更為高效。
      既然volatile關(guān)鍵字已經(jīng)實(shí)現(xiàn)了線程間數(shù)據(jù)同步,又要synchronized干什么呢?呵呵,它們之間有兩點(diǎn)不同。首先,synchronized獲得并釋放監(jiān)視器——如果兩個(gè)線程使用了同一個(gè)對(duì)象鎖,監(jiān)視器能強(qiáng)制保證代碼塊同時(shí)只被一個(gè)線程所執(zhí)行——這是眾所周知的事實(shí)。但是,synchronized也同步內(nèi)存:事實(shí)上,synchronized在“主”內(nèi)存區(qū)域同步整個(gè)線程的內(nèi)存。因此,執(zhí)行g(shù)eti3()方法做了如下幾步:
    1. 線程請(qǐng)求獲得監(jiān)視this對(duì)象的對(duì)象鎖(假設(shè)未被鎖,否則線程等待直到鎖釋放)
    2. 線程內(nèi)存的數(shù)據(jù)被消除,從“主”內(nèi)存區(qū)域中讀入(Java虛擬機(jī)能優(yōu)化此步。。。[后面的不知道怎么表達(dá),汗])
    3. 代碼塊被執(zhí)行
    4. 對(duì)于變量的任何改變現(xiàn)在可以安全地寫到“主”內(nèi)存區(qū)域中(不過(guò)geti3()方法不會(huì)改變變量值)
    5. 線程釋放監(jiān)視this對(duì)象的對(duì)象鎖
      因此volatile只是在線程內(nèi)存和“主”內(nèi)存間同步某個(gè)變量的值,而synchronized通過(guò)鎖定和解鎖某個(gè)監(jiān)視器同步所有變量的值。顯然synchronized要比volatile消耗更多資源。

    附英文原文:
    What does volatile do?

  • int i1;                          int geti1() {return i1;}
  • volatile int i2;              int geti2() {return i2;}
  • int i3; synchronized     int geti3() {return i3;}
  • geti1() accesses the value currently stored in i1 in the current thread. Threads can have local copies of variables, and the data does not have to be the same as the data held in other threads. In particular, another thread may have updated i1 in it’s thread, but the value in the current thread could be different from that updated value. In fact Java has the idea of a “main” memory, and this is the memory that holds the current “correct” value for variables. Threads can have their own copy of data for variables, and the thread copy can be different from the “main” memory. So in fact, it is possible for the “main” memory to have a value of 1 for i1, for thread1 to have a value of 2 for i1 and for thread2 to have a value of 3 for i1 if thread1 and thread2 have both updated i1 but those updated value has not yet been propagated to “main” memory or other threads.

    On the other hand, geti2() effectively accesses the value of i2 from “main” memory. A volatile variable is not allowed to have a local copy of a variable that is different from the value currently held in “main” memory. Effectively, a variable declared volatile must have it’s data synchronized across all threads, so that whenever you access or update the variable in any thread, all other threads immediately see the same value. Of course, it is likely that volatile variables have a higher access and update overhead than “plain” variables, since the reason threads can have their own copy of data is for better efficiency.

    Well if volatile already synchronizes data across threads, what is synchronized for? Well there are two differences. Firstly synchronized obtains and releases locks on monitors which can force only one thread at a time to execute a code block, if both threads use the same monitor (effectively the same object lock). That’s the fairly well known aspect to synchronized. But synchronized also synchronizes memory. In fact synchronized synchronizes the whole of thread memory with “main” memory. So executing geti3() does the following:

    1. The thread acquires the lock on the monitor for object this (assuming the monitor is unlocked, otherwise the thread waits until the monitor is unlocked).
    2. The thread memory flushes all its variables, i.e. it has all of its variables effectively read from “main” memory (JVMs can use dirty sets to optimize this so that only “dirty” variables are flushed, but conceptually this is the same. See section 17.9 of the Java language specification).
    3. The code block is executed (in this case setting the return value to the current value of i3, which may have just been reset from “main” memory).
    4. (Any changes to variables would normally now be written out to “main” memory, but for geti3() we have no changes.)
    5. The thread releases the lock on the monitor for object this.

    So where volatile only synchronizes the value of one variable between thread memory and “main” memory, synchronized synchronizes the value of all variables between thread memory and “main” memory, and locks and releases a monitor to boot. Clearly synchronized is likely to have more overhead than volatile.

    posted on 2008-04-24 10:15 周銳 閱讀(385) 評(píng)論(2)  編輯  收藏 所屬分類: Java
    主站蜘蛛池模板: 四虎影视久久久免费| 国产免费一区二区三区VR| 猫咪免费人成网站在线观看入口| 亚洲黄色三级视频| 亚洲乱码中文字幕综合| 成人永久免费高清| 成人AV免费网址在线观看| 永久免费av无码入口国语片| 特色特黄a毛片高清免费观看| 国产亚洲精aa在线看| 亚洲第一页在线视频| 久久久无码精品亚洲日韩蜜桃| 亚洲视频在线免费| 免费一级国产生活片| 免费看少妇作爱视频| 久久不见久久见中文字幕免费| 亚洲w码欧洲s码免费| 一级毛片成人免费看免费不卡 | 无码av免费毛片一区二区| 永久在线观看免费视频| 精品一区二区三区高清免费观看 | 99久久精品国产免费| 久操视频在线免费观看| 中国黄色免费网站| 成人免费ā片在线观看| 亚欧国产一级在线免费| 91av免费在线视频| 99精品视频在线观看免费| 老司机精品免费视频| 精品久久久久久国产免费了 | 日本亚洲国产一区二区三区| 亚洲成A人片在线观看无码3D | 亚洲欧美日韩中文字幕一区二区三区| 亚洲av无码片在线观看| 亚洲免费中文字幕| 亚洲婷婷第一狠人综合精品| 91在线亚洲综合在线| 亚洲国产精品网站在线播放 | 美女视频黄是免费的网址| 99久久这里只精品国产免费| 青青在线久青草免费观看|