標籤:cep 提交 new 資料 syn bool tar tst 需要
原子性
原子性是指一個操作是不可中斷的。即使是在多個線程一起執行的時候,操作一旦開始,也不會被其他線程幹擾。即原子操作是一個做小操作。
例如 i++,其實經曆了讀,算,賦值絕對算不上是一個原子操作。一個i = 10這樣的賦值操作可以稱為原子操作。
java.util.comcurrent.atomic包裡都是關於原子操作的類,有時間會另寫一篇部落格。
有序性
提到有序那必然就有亂序,而亂序是因為jvm的指令重排最佳化而產生的。
我們要想完全保住有序性,需要給對象加同步鎖(synchronized),這樣做實際上就是單線程執行了。
可見度
可見度是指當一個線程修改了某一個共用變數的值,其他線程是否能夠立即知道這個修改。
而其他線程看不到實際上是因為每個cpu都有寄存器,有一個線程把寄存器裡的值修改了並提交到jvm了,而還有一個cpu的寄存器裡存著資料的緩衝,等它回頭看jvm的時候,發現值已經變了。
Java提供了volatile關鍵字來保證可見度。
當一個共用變數被volatile修飾時,它會保證修改的值會立即被更新到主存,當有其他線程需要讀取時,它會去記憶體中讀取新值。
下面用一段代碼來做測試。
public class VisibilityTest extends Thread{
//如果沒有關鍵字volatile,會發現這個線程停不掉,可自行測試。 private volatile boolean stop; public void run() { int i = 0; while (!stop) { i++; } System.out.println("finish loop,i=" + i); } public void stopIt() { stop = true; } public boolean getStop() { return stop; } public static void main(String[] args) throws InterruptedException { VisibilityTest visibilityTest = new VisibilityTest(); visibilityTest.start(); visibilityTest.sleep(1000); visibilityTest.stopIt(); System.out.println(visibilityTest.getStop()); }}
Happen-Before原則
? 程式順序原則:一個線程內保證語義的串列性 a=1 b=a+1
? volatile規則:volatile變數的寫,先發生於讀,這保證了volatile變數的可見度
? 鎖規則:解鎖(unlock)必然發生在隨後的加鎖(lock)前
? 傳遞性:A先於B,B先於C,那麼A必然先於C
? 線程的start()方法先於它的每一個動作 ? 線程的所有操作先於線程的終結(Thread.join())
? 線程的中斷(interrupt())先於被中斷線程的代碼
? 對象的建構函式執行結束先於finalize()方法
Java並發之原子性,有序性,可見度,以及Happen-Before原則