在多執行緒中,volatile關鍵字是很重要的乙個知識點,在多執行緒共享資源的時候,每個執行緒資料對外都是不可見的,這就容易出現」髒讀」現象,其實就是執行緒私有堆疊中的資料和公共堆疊中的資料不同步造成的.解決這樣的問題,就要使用volatile關鍵字了。
那valotitle關鍵字有什麼用,他是強制執行緒從公共堆疊中讀取變數的值,以保證讀取的是最新的,增加了例項變數的可見性。
來個demo驗證下
public
class
mythread
extends
thread
system.out.println("run end");
}public
void
setrun(boolean isrun)
} public
static
void
main(string args) throws exception
列印結果:
執行緒一直處於運轉狀態,run end無法執行到;
修改一下假如volatitle關鍵字
public
class
mythread
extends
thread
system.out.println("run end");
}public
void
setrun(boolean isrun)
}
結果:
完全正確
但是volatile只解決了執行緒的可見性,並不能保證原子性
public
class
mythread
extends
thread
private
void
add()
system.out.println("count="+count);
}}public
static
void
main(string args) throws exception
for(mythread r:rs)
}
列印結果:
不等10000,那怎麼改?只需要在add方法加synchronized鎖,將add變為靜態方法即可
synchronized
private
static
void
add()
system.out.println("count="+count);
}
結果:
關鍵字volatilt提示執行緒每次從共享記憶體中讀取變數,而不是從私有記憶體中讀取變數,保證了同步資料的可見性。但是這裡需要注意的而是,修改例項變數中的資料,如i++,這樣的操作其實不是乙個原子操作,也就是非執行緒安全,表示式i++的操作分解步驟如下:
1)從記憶體中取i的值
2)計算i的值
3)將i的值寫到記憶體中。
來看一下變數在記憶體中的工作過程:
在多執行緒環境中,use和assign是多次出現的,但這一操作並不是原子性,也就是在read和load之後,如果記憶體count變數發生修改之後,執行緒工作記憶體中的值由於已經載入,不會產生對應的變化,也就是私有記憶體和工作記憶體的變數不同步,所以計算出來的結果和預期不一樣,也就是非執行緒安全問題。
對於volatile修飾的變數,jvm只是保證從主記憶體載入到工作記憶體中的值是最新的,例如執行緒1和2在進行read和load的操作中,發現主記憶體中的count的值都是5,那麼都會載入這個最新的值,也就是說volatile關鍵字解決的是變數讀時的可見性問題,但不保證原子性,對於多個執行緒訪問同乙個例項變數還是需要加同步鎖。
成功累加到10000
public
class
mythread
extends
thread
private
void
add()
}public
static
void
main(string args) throws exception
for(thread m:rs)
thread.sleep(2000);
system.out.println(mythread.atomic.get());
}
結果的一種可能:
雖然最終結果是對的,但是列印明顯不符合預期,+1這個明顯沒有列印出來。雖然add方法是原子操作,但是呼叫方法卻不是原子的,解決這種問題,必須用同步。
改進後的
public
class
mythread
extends
thread
synchronized
private
void
add()
}
列印結果:
多執行緒 Volatile 關鍵字
volatile 關鍵字的作用是變數在多個執行緒之間可見,但不保證資料的原子性 package com.jvm.test class threadvolatiledemo extends thread system.out.println 執行緒停止 public void setruning bo...
多執行緒之volatile關鍵字
現代計算機都是馮諾依曼結構的 volatile 變數具備兩種特性,其一是保證該變數對所有執行緒可見,這裡的可見性指的是當乙個執行緒修改了變數的值,那麼新的值對於其他執行緒是可以立即獲取的。其二 volatile 禁止了指令重排。多執行緒的執行可能造成變數資料的不一致 把該變數宣告為volatile ...
JAVA多執行緒之 volatile關鍵字
概要 public class mythread implements runnable override public void run system.out.println 終止執行。public static void main string args throws interruptedex...