多線程編程 實戰篇秘籍 (二)

來源:互聯網
上載者:User

volatile 變數

volatile 是用來保證[記憶體同步]的關鍵字,記憶體同步是說在某個線程中修改某執行個體欄位能夠及時地
更新到主儲存區,而某線程如果需要引用該欄位也能及時地從主儲存區中得到最新的資料.

簡單說它是當前線程的工作儲存區和主儲存區對某欄位的及時同步,所以我們說它是[記憶體同步],但它
不是線程同步.

也就是說,一個線程對 volatile欄位進行更新時,它只會把更新後的值及時地同步到主儲存區,而並不
保證其它線程中該欄位的值得到及時更新.(不過其它線程如果要對該欄位訪問的話還會及時從主儲存
區COPY的).

因為只保證當前線程中對volatile欄位的更新會及時與主儲存區同步,所以volatile並不能達到同步的
功能.比如線程A和B最初的 volatile int x = 10;當線程A獎x +1後,線程A的工作儲存區的x和主工作存
儲區的x都為11,但這時線程B中的x仍然為10,只有當線程B需要訪問x時才會從主儲存區中COPY x的值使
x為11.

所以 volatile 關鍵字並不能保證多個線程同時對主儲存區欄位的"同步".只有在某種條件下,最合適的
情況就是只有某一線程修改某一變數後,其它線程只是對其進行引用而不再更新.比如我們設定的線程
退出標記.
volatile boolean exit = false;

這樣的變數用於在所有線程中判斷是否退出,其中任何一個線程修改為true後,會及時更新主儲存區中
該變數的值,而其它線程也能及時擷取到該值的變化而及時地結束自己的工作.

volatile 可以保證 double和long操作是原子操作.

原子操作(atomic)是指對變數從主儲存COPY到線程工作儲存區時,經及從線程的工作儲存區寫回到主儲存
區時,不會因為其它線程的同時操作而改變變數的值.

對於普通變數,double和long在設計的時候並不是原子型操作,也就是對地這兩種變數的上述操作在一定情
況下可能會因為其它線程而覆蓋我們的操作.那麼volatile可以保證double和long象int一樣的atomic操作.
 

另外,從JSR133以後,由於對JAVA記憶體模型進行的修複,volatile 變數有了更大的作用.

對於前面討論的比檢鎖問題,如果(這裡只是假設,事實上我們不會這樣做,後面說原因)我們對instance(obj)變數聲明為

volatile 的,那麼在第一個線程初始化後,如果線程a中的Date d是可訪問的,那麼對於線程B中也是可見的.也就是說它修補了雙驗鎖的缺陷,使JAVA的雙檢鎖不再存在陷井.

那麼真的這麼簡單地就修補了這個陷井嗎?從理論上說,是的.jmm在JDK1.5以後保證做到如果instance是volatile 的那麼雙

檢鎖就能正確工作。

 

但實際上,這樣做已經沒有意義。因為在JDK1.5以後DCL已經沒有存在的必要,DCL存在背景是在JDK1.5以前無競爭同步的極低效能和緩慢的JVM啟動下多線程並發訪問instance的機會很大(如果JVM啟動很快,instance構造到快得讓其它線和沒有機會捕捉到不可見度的發生),在JDK1.5以後這樣的最佳化效能幾乎可以忽略。而在JDK1.5之前它又不能保證正確性。所以DCL已經沒有什麼意義了。一個更好的模型見我的深入研究DCL一文。

 

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.