1.有序性
當**前後順序發生變化互不影響時,虛擬機會對**進行重排,但是這個操作可能會影響其他執行緒的執行,例子如下:
public class test
});thread t2 = new thread(new runnable()
});t1.start();
t2.start();
t1.join();
t2.join(); //等待t1,t2執行緒的結束,避免a,b還沒賦值到map中就將其新增到set中
set.add("a="+map.get("a")+",b="+map.get("b")); //將map中的值新增到set中
system.out.println(set); //列印set}}
}
列印結果:
[a=0,b=0, a=1,b=0, a=0,b=1,a=1,b=1]
有上述4種輸出, 結果 1,1 是**發生重排後的結果。
2.可見性。
當兩個執行緒t1,t2呼叫乙個變數a時會發生的問題,首先t1從主存中讀取了a的值,並將a的值發生了改變,在t1將a的值送回主存中的時候,t2又從主存中讀取了a的值,但是t2讀取到的值是改變前的值,並不是t1返回給主存的值,此時就發生了問題。例子如下:
public class test4_1
system.out.println("方法執行完畢");
}public static void main(string args)
}).start();
//這裡需要讓執行緒睡眠一會,因為執行的m方法一開始還會不斷向主存中讀取a的值。
try catch (interruptedexception e)
//將a的值改為false;
test.a = false;
system.out.println("a的值為" + test.a);
}}
3.原子性
完成乙個事物,事物中可能會有多個操作。要麼都執行,或者都不執行。
比如轉賬:小明轉給小紅100塊錢,假設這項事務 1.從小明錢包中扣除100元,2.將小紅錢包中的值加上100。在此過程中 如果第二步操作出現了異常,小紅的錢沒加上,而小明的錢已經扣除,這樣顯然是不行的,所以兩步操作要麼都執行,要麼都不知道。
例子**如下:
public class test4_2
//列印執行完畢的執行緒名
system.out.println(thread.currentthread().getname() + "執行完畢");
}}).start();
}//使執行緒睡眠三秒鐘,給上面五個執行緒足夠的執行時間
thread.sleep(3000);
//列印a的值,可以發現上面五個執行緒執行完後a的值並不等於預想值。
system.out.println(a);
}}
在上述的操作中,列印a的值會小於等於500000000,原因就是沒***原子性,也就是可能會有多個執行緒執行到上述標記(1)中,他們獲取到的a的值是相同,但是他們都執行了a++然後將a的值返回到主存這個操作,也就是說返回的值比原來多了1,但是所有執行緒的執行次數大於1,所以最後的值會比預計的小或者等於。
解決辦法可以使用atomicinteger這個類,運用了cas原理
併發程式設計的三大特性
1 原子性 對於成員變數a來說,如果執行緒a執行以下操作 a 此時需要分三步執行 1 讀取a的值 2 將a的值加1 3 將加1後的值賦給a 在執行以上三步過程中,如果另乙個執行緒b對a進行了操作,那麼就不能保證原子性了。要保證原子性,可以加鎖,如synchronized 2 可見性 要理解可見性,需...
物件導向程式設計三大特性
類和物件的關係 類 而物件則是以類為模板所建立的。類的組成 物件建立記憶體模型 1 當程式開始執行,方法區以載入好程式所需類的位元組碼檔案。2 棧記憶體引導程式,當執行到需要建立物件時,會在堆記憶體中建立物件,此時物件的成員變數為初始值,成員方法為位址,指向方法區中的類成員方法。3 堆記憶體中所建立...
物件導向程式設計三大特性(csharp)
1.封裝 2.繼承 3.多型 不扯別的,看 就好 using system 程式的宣告 namespace demo0709 交通工具類 class transport public transport int id,string name public override string tostri...