1、原子性
對於成員變數a來說,如果執行緒a執行以下操作:
a++;
此時需要分三步執行:
(1)讀取a的值
(2)將a的值加1
(3)將加1後的值賦給a
在執行以上三步過程中,如果另乙個執行緒b對a進行了操作,那麼就不能保證原子性了。
要保證原子性,可以加鎖,如synchronized
2、可見性
要理解可見性,需要先理解cpu的快取記憶體。快取記憶體是cpu的一塊兒快取區。如果執行緒修改了某個變數的值,那麼是先將修改過的值先放入快取區,然後滿足一定條件後才會同步到記憶體區。同步到記憶體區後,其他執行緒才可以看見變數的改變。
可見性是指,當有乙個執行緒修改某個成員變數的值時,其他變數可以立馬看到修改過的值。
比如:int i=0,j=10;
i=j;
如果執行緒a執行了以上**,這時如果還未將i等於10的結果由快取記憶體區同步到記憶體區,那麼b執行緒讀取到的i的值就是0。
要保證可見性,需要用volatile關鍵字,原理是,執行緒b會將快取記憶體區的結果重新整理到記憶體,它再去讀取記憶體。這樣讀取的i的值就是10。
3、有序性
處理器為了提高程式執行效率,可能會對輸入**進行優化,它不保證程式中各個語句的執行先後順序同**中的順序一致,但是它會保證程式最終執行結果和**順序執行的結果是一致的。比如:
int i=10;//語句1
int j=10;//語句2
在執行時,有可能對**進行重排序,比如先執行語句2,再執行語句1。但是如果**,程式設計下邊這樣:
int i=0;
int j=0;
j++;//語句3
i=j+1;//語句4
這時,語句3和語句4並不會進行重排序。因為語句3和4之間有依賴關係,重排序後會影響結果。
但是以上說的是單執行緒的情況。下面看多執行緒的情況,如下**:
boolean flag=false;
private context context;
//執行緒1
context=loadcontext();//語句1
flag=true;//語句2
//執行緒2
if(flag)
如果執行緒1執行的時候,語句1和語句2進行了重排序,先執行語句2,在還沒有執行語句1時,這時執行緒2 將要執行if,那麼就會進入到if語句塊中,而context還是null,所以會出錯。
可以用volatile關鍵字,禁止被它修飾的變數發生指令重排操作。是通過記憶體屏障去完成的禁止指令重排序。
併發程式設計三大特性
1.有序性 當 前後順序發生變化互不影響時,虛擬機會對 進行重排,但是這個操作可能會影響其他執行緒的執行,例子如下 public class test thread t2 new thread new runnable t1.start t2.start t1.join t2.join 等待t1,t...
物件導向程式設計三大特性
類和物件的關係 類 而物件則是以類為模板所建立的。類的組成 物件建立記憶體模型 1 當程式開始執行,方法區以載入好程式所需類的位元組碼檔案。2 棧記憶體引導程式,當執行到需要建立物件時,會在堆記憶體中建立物件,此時物件的成員變數為初始值,成員方法為位址,指向方法區中的類成員方法。3 堆記憶體中所建立...
Java物件導向程式設計的三大特性
繼承 繼承是一種聯結類的層次模型,並且允許和鼓勵類的重用,它提供了一種明確表述共性的方法。物件的乙個新類可以從現有的類中派生,這個過程稱為類繼承。新類繼 承了原始類的特性,新類稱為原始類的派生類 子類 而原始類稱為新類的基類 父類 派生類可以從它的基類那裡繼承方法和例項變數,並且類可以修改或增 加新...