1. 程式人生 > >java 執行緒安全的全域性計數器-AtomicInteger原子操作類

java 執行緒安全的全域性計數器-AtomicInteger原子操作類

首先 , 測試一下正常程式碼

public class Test1 {
    public static int count = 0;
 
    public static void main(String[] args) {
        for (int i = 0; i < 10000; i++) {
            new Thread() {
                public void run() {
                    count++;
                }
            }.start();
        }
        System.out.println("count: " + count);
    }
 
}

輸出的結果為count: 9983,這個值不定,每次測試都可能不一樣,很顯然,100個執行緒跑++操作,結果並沒有像預期的那樣count: 10000

接下來換成 volatile修飾count變數

public class Test3 {
    static volatile int count = 0;
 
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 100; i++) {
            new Thread() {
                public void run() {
                    for (int j = 0; j < 100; j++) {
                        count++;
                    }
                }
            }.start();
        }
        Thread.sleep(1000);
        System.out.println("volatile count: " + count);
    }
}

結果出現volatile count: 9984,果然還是出現問題了,volatile僅僅保證變數線上程間保持可見性,卻依然不能保證非原子性的操作。 

最後用AtomicInteger類

public class Test2 {
 
    public static AtomicInteger count = new AtomicInteger(0);
 
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 100; i++) {
            new Thread() {
                public void run() {
                    for (int j = 0; j < 100; j++) {
                        count.getAndIncrement();
                    }
                }
            }.start();
        }
        Thread.sleep(1000);
        System.out.println("AtomicInteger count: " + count);
    }
}

結果每次都輸出"AtomicInteger count: 10000",滿足要求

concurrent(我這裡是jdk1.8)包下提供了12種原子操作型別

atomic包下提供了AtomicBoolean/AtomicLong/AtomicInteger三個原子更新基本型別,以AtomicInteger為例,其他兩種基本類似。以下是AtomicInteger囊括的大致方法

public final int getAndSet(int newValue)       //給AtomicInteger設定newValue並返回加oldValue
public final boolean compareAndSet(int expect, int update)    //如果輸入的值和期望值相等就set並返回true/false
public final int getAndIncrement()     //對AtomicInteger原子的加1並返回當前自增前的value
public final int getAndDecrement()   //對AtomicInteger原子的減1並返回自減之前的的value
public final int getAndAdd(int delta)   //對AtomicInteger原子的加上delta值並返加之前的value
public final int incrementAndGet()   //對AtomicInteger原子的加1並返回加1後的值
public final int decrementAndGet()    //對AtomicInteger原子的減1並返回減1後的值
public final int addAndGet(int delta)   //給AtomicInteger原子的加上指定的delta值並返回加後的值

相應的,concurrent包下除了提供的原子更新基本型別,還有原子更新資料、原子更新引用型別、原子更新欄位類,最常用的也就是原子更新基本型別了。