Java併發編程(二)原子性

Java極客  |  做者  /  鏗然一葉
這是Java極客的第 30 篇原創文章

1、一個小測驗

併發狀況下,下面兩個類是否線程安全?java

public class Counter {
    private int count;
    
    public void increase() {
        count = count + 1;
    }
    
    public int getCount() {
      return count;
    }
}

public class Basket {
    //Vector是線程安全的集合
    Vector<Fruit> v = new Vector<Fruit>();

    public void put(Fruit fruit) {
        v.add(fruit);
    }

    public Fruit tackOut() throws Exception {
        if (v.size() > 0) {
            return v.remove(0);
        } else {
            throw new Exception("There is no fruit in basket.");
        }
    }
}
複製代碼

答案:以上兩個類在併發狀況下均不能保證線程安全。編程

2、線程安全和原子性

線程安全:當多個線程訪問某個類時,這類始終都能表現出正確的行爲,那麼這個類是線程安全的。緩存

原子性:一個或者多個操做在CPU執行的過程當中不被中斷的特性稱爲原子性。安全

而以上兩個類不能保證操做原子性致使不能表現正確的行爲,所以都不是線程安全的。多線程

1.在類Counter中,如下代碼實際執行了三個指令:併發

count = count + 1;
複製代碼

在多線程併發狀況下因爲線程切換會致使計算結果不正確。post

注:圖片參考Java併發編程實戰優化

2.在類中的以下代碼不是原子的,可能會致使拋出空指針異常和預期不符:ui

if (v.size() > 0) {
    return v.remove(0);
}
複製代碼

3、修正

原子性能夠經過加鎖來解決,修正以下:spa

public class Counter {

    private int count;
    
    public synchronized void increase() {
        count = count + 1;
    }
    
    /** 原子操做可不加同步關鍵字 */
    public int getCount() {
      return count;
    }
}

public class Basket {

    Vector<Fruit> v = new Vector<Fruit>();

    /** 原子操做可不加同步關鍵字 */
    public void put(Fruit fruit) {
        v.add(fruit);
    }

    /** 加上synchronized關鍵字 */
    public synchronized Fruit tackOut() throws Exception {
        if (v.size() > 0) {
            return v.remove(0);
        } else {
            throw new Exception("There is no fruit in basket.");
        }
    }
}
複製代碼

end.


相關閱讀:
Java併發編程(一)知識地圖
Java併發編程(三)可見性
Java併發編程(四)有序性
Java併發編程(五)建立線程方式概覽
Java併發編程入門(六)synchronized用法
Java併發編程入門(七)輕鬆理解wait和notify以及使用場景
Java併發編程入門(八)線程生命週期
Java併發編程入門(九)死鎖和死鎖定位
Java併發編程入門(十)鎖優化
Java併發編程入門(十一)限流場景和Spring限流器實現
Java併發編程入門(十二)生產者和消費者模式-代碼模板
Java併發編程入門(十三)讀寫鎖和緩存模板
Java併發編程入門(十四)CountDownLatch應用場景
Java併發編程入門(十五)CyclicBarrier應用場景
Java併發編程入門(十六)秒懂線程池差異
Java併發編程入門(十七)一圖掌握線程經常使用類和接口
Java併發編程入門(十八)再論線程安全


Java極客站點: javageektour.com/

相關文章
相關標籤/搜索