咱們首先看一個例子:產生一個整數序列,每一個值都必須是遞增惟一的。咱們能夠用如下代碼實現一個: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提供的原子工具類。