在看別人的線程代碼的時候,常常會看到「volatile」關鍵字來修飾某個變量。可是他究竟起一個什麼做用呢?java
在看到其餘網友對volatile理解,大概意思是。這個關鍵字修飾的變量對於每個線程都是共享的,每一個線程都是能夠看到這個volatile修飾的最新的值。這個理解是沒錯的。接下來將詳細說明volatile這個關鍵字。linux
咱們常常會看到下面這樣的代碼windows
volatile
boolean
flag =
false
;
centos
while
(flag){
緩存
doSomeThing();
安全
}
服務器
設置一個volatile變量,而後修改這個值用來判斷線程隊列是否滿了?回憶一下是否常常看到這樣的代碼?多線程
java語言提供一種稍弱的的同步機制,即volatile變量。用來確保將變量的更新操做通知到其餘線程。也是內存可見性,防止編譯器將操做重排序,致使變量被緩存,從而不能被程序訪問到,致使拿到的變量可能不是最新的。這樣將會致使,程序一致執行,或者數據錯誤,有災難性的後果。jvm
而若是咱們在將變量聲明爲volatile,編譯器與運行時都會注意到這個變量是共享的,所以不會將改變量上的操做與其餘內存操做一塊兒重排序。volatile變量不會被緩存在寄存器或者對其餘處理器看不到的地方,所以在讀取volatile類型的變量總會返回最新寫入的值。從而使的程序可以按照預期的執行。測試
可是volatile雖然對於其餘線程具備內存可見性,可是對於counter++,這樣的操做仍是很危險。volatile不能保證遞增或者遞減操做的原子性。
補充:最近在看jvm的一本書的時候,感受講的很清楚,特意貼出來
由於,咱們的JIT編譯器在server模式和client模式編譯不一樣,server模式爲了使線程運行更快,若是其中一個線程更改了變量boolean flag 的值,那麼另一個線程會看不到,由於另一個線程爲了使得運行更快因此從寄存器或者本地cache中取值,而不是從內存中取值,那麼使用volatile後,就告訴不管是什麼線程,被volatile修飾的變量都要從內存中取值。《內存柵欄》
再次補充:以前在qq羣裏面討論,有人說volidate是不安全的,我本身寫段代碼,起不少線程不停累加volidate修飾的變量。測試結果再windows上安裝的jvm確實不安全,我是以客戶端模式運行,可是我在linux(centos6.3 64位)無論是客戶端模式仍是服務器模式,都是安全的,volidate到底如何訪問,是否安全主要和jvm,以及操做系統有關,有興趣的能夠本身試試。
再次補充:對於volidate 最好不要用++之類的操做符,來測試,由於在++上,volidate對他支持並很差
補充:
(185498480) 16:44:08 我以爲根本就沒鎖吧 我以爲VOLATILE只是一個編譯指示 朱(185498480) 16:45:27 就是告訴你們 全部線程要取和寫這個變量的值 都要到指定的內存去操做 讀寫語句在編譯的時候都會被編譯成這樣運行 這樣就保證的全部的可見性 朱(185498480) 16:46:39 由於根本沒鎖 天然沒順序控制了 不會讀棧 不會保存到CPU寄存器等等 都在一個指定的內存點 老船長(108439162) 16:48:42 volatile是強制變量寫到內存中,而其餘的變量可能會在棧中,或者寄存器中,不會時時都寫在內存中,保證其餘線程也能看到。