1. 程式人生 > >《java併發程式設計實戰》之 執行緒安全性

《java併發程式設計實戰》之 執行緒安全性

1.執行緒安全性

當多個執行緒訪問某個類時,不管執行時環境採用何種排程方式或者這些執行緒將如何交替執行,並且在主調程式碼中不需要任何額外的同步或協同,這個類都能表現出正確的行為,那麼這個類就是執行緒安全的。

無狀態物件一定是執行緒安全的,何為無狀態,就是類中不包含任何域,也不包含各種其他類的飲用,就只有區域性變數 。

2.原子性

執行緒中的 ++count 或者 count++ 那都非原子性,而是  讀取--修改--寫入,
如果過程中有兩個執行緒在跑,由於不恰當的執行時序出現不正確的結果稱為  “競態條件”

2.1 競態條件

public class A{
    private B b = null;
    
    public B get(){
        if(b == null)     // thread1,thread2 同時判斷為null
            b = new B();
        return b ;
    }
} 

2.3 複合操作

避免競態條件問題,就要a執行緒在修改變數時,b執行緒已經執行完,或者不執行。

對同一個狀態有A B 操作,一個執行緒執行A操作,另一個執行緒執行B操作,要麼是已經執行完,要不就是完全不執行,A B操作都是原子操作。


++count 是複合操作,要以執行緒安全的方式去修復執行。

使用執行緒安全的物件進行記錄

public class A{
    private final AtomicLong count = new AtomicLong(0);
    
    public long getCount(return count.get());
    
    public void set(){
        count.incrementAndGet();
    }
} 

3.加鎖機制

3.1 內建鎖(同步程式碼塊 synchronized)

同步程式碼塊
synchronized(lock){
    //訪問或修改由鎖保護的共享狀態
}


某個執行緒可以重如自己持有的鎖的程式碼中,每個鎖有一個計數器,所有者執行緒,計數器值=0
,鎖未被持有,執行緒請求未被持有的鎖,jvm記下鎖持有者,計數器值+1, 同一個執行緒再次獲得鎖,計數值+1,執行緒退出,則-1.



public class A{
    public synchronized void do{
        ...
    }
}



public class B extends A{
    public synchronized void do{
        super.do();   //同一個物件,可以多次重入加鎖的程式碼。
    }
}