java併發編程——原子變量介紹

  • 第一部分:原子變量的前世

咱們首先看一個例子:產生一個整數序列,每一個值都必須是遞增惟一的。咱們能夠用如下代碼實現一個:java

public class UnsafeSequence{
    private int value;
    
    public int getNext(){
        return value++;
    }
}

上面的代碼在單線程環境下運行沒有任何問題,可是若是在多線程併發訪問的狀況下它就會有問題。仔細分析getNext方法實際上它包含了三步操做:安全

第一步:得到當前value值;多線程

第二步:把當前value值+1;併發

第三步:返回當前value值。高併發

多個線程併發執行上面方法時,返回的value值極有多是相同的,這顯然違背了咱們的初衷,因此這個類不是線程安全的。以下圖所示:工具

咱們能夠用前面講到的加鎖知識把該類修改爲線程安全的,最簡單的就是給方法加synchronized;atom

public class SafeSequence{
    private int value;
    
    public synchronized int getNext(){
        return value++;
    }
}

修改完之後這個類如今是線程安全的了。若是有線程正在執行getNext方法,那麼其餘線程就等待當前線程執行完畢後再執行,這樣就保證了整個操做的原子性。當這樣作仍是會給開發人員帶來額外的負擔,開發人員不得不去思考在哪些調用是須要共享的,同時還得避免死鎖以及其餘活躍性問題。因而,Java 5以後java.util.concurrent.atomic包下面的支持原子操做的類便誕生了。spa

  • 第二部分:原子變量的使用

java.util.concurrent.atomic包下面有不少支持以原子方式更新的類,比較經常使用的有:AtomicBoolean,AtomicInteger,AtomicLong和AtomicReference<V>。咱們就以AtomicInteger類爲例,講講它的用法:線程

仍是上面的產生一個整數序列的例子,要求序列值惟一,用AtomicInteger就能夠很容易實現。code

AtomicInteger ai = new AtomicInteger();
ai.incrementAndGet();

代碼是否是很簡潔,他一樣線程安全的實現了一個惟一序列,使用起來更加方便和簡單。AtomicInteger有兩個構造方法,同時提供了不少其餘支持原子操做的方法,

public class AtomicInteger{
    public int addAndGet(int delta);//以原子方式將給定值與當前值相加,
    public int getAndAdd(int delta);

    public int decrementAndGet();//以原子方式將當前值減1,相似i--,--i
    public int getAndDecrement();

    public int getAndIncrement();//以原子方式將當前值加1,相似i++,++i
    public int incrementAndGet();

    public int get();//獲取當前值
    public void set(int value);//設置給定值

    public void lazySet(int newValue);//最終設置某值
    

    …………
}

看了這些方法的方法名我想你就已經明白瞭如何使用他們。AtomicBoolean,AtomicLong和AtomicReference<V>的使用與AtomicInteger相似,能夠經過查看API瞭解他們的具體方法。

原子類的出現簡化了咱們程序中的原子操做,使程序更加安全穩固。並且,在高併發的場景下,原子類的執行效率也要高於加鎖的原子操做。所以,若是在項目中有相似的功能,不妨就試試java提供的原子工具類。

相關文章
相關標籤/搜索