1. 程式人生 > >java併發(一)執行緒安全概念

java併發(一)執行緒安全概念

java中包含幾種執行緒級別:

不可變:這種級別是最簡單的執行緒安全方式,即:如果帶有狀態的變數是基本資料型別定義成final,是引用型別,則其物件不能有改變自身的行為
(如String,enum,Number的部分子類:Integer,Long等[不包括AtomicInteger,AtomicLong等])

絕對安全:不論執行環境如何,呼叫者都不需要任何額外的措施來保證執行緒安全,要想達到這點,可能會付出巨大的代價。

相對安全:對物件的單獨操作是執行緒安全的(如上面多執行緒訪問remove方法,add方法),但對於特定順序的連續呼叫,就需要呼叫者使用額外的同步手段來保證執行緒安全。

以java.util.Vector舉例,在java中稱它為執行緒安全的物件,這是因為Vector中所有的行為都被synchronized修飾,這也是java通俗意義上講的執行緒安全的概念,然而Vector實際上只是執行緒相對安全的,並非絕對安全,在涉及特定順序的連續呼叫就會出現問題:

/*
此程式先對Vector初始化1000個元素,然後每次開啟2個執行緒,1個執行緒執行刪除元素操作,1個執行緒執行獲取元素操作。
 當一個錯誤的時機(獲取執行緒進入for迴圈執行到當前Vector的size-x時,被刪除執行緒搶走執行權刪除了x個或以上的元素)
 此時獲取執行緒才得到執行權,結果此前的Vector的長度已經不夠size-x,就會導致角標越界異常。
*/
private static Vector<Integer> v = new Vector<>();
    static{
        for(int i=0; i<1000; i++){
            v.add(i);
        }
    }
    public
static void main(String[] args) { while(true){ new Thread(new Runnable() { @Override public void run() { for(int i=0; i<v.size(); i++){ v.remove(i); } } }).start(); new
Thread(new Runnable() { @Override public void run() { for(int i=0; i<v.size(); i++){ v.get(i); } } }).start(); //不要產生過多的執行緒,防止作業系統假死 if(Thread.activeCount()>20)break; } }

執行緒相容:指物件本身不是執行緒安全的,但是呼叫者可以通過正確的同步手段來保證執行緒安全,也就是我們通常說的執行緒不安全。

執行緒對立:指物件無論是否採用同步操作,都無法在多執行緒中併發使用的程式碼,由於java天生具備多執行緒特性,這種情況很少見,且通常是有害的,應當儘量避免。
(常見的有Thread物件的resume方法和suspend方法[已廢棄],System的setIn,setOut,runFinalizersOnExit)