java 執行緒安全的全域性計數器-AtomicInteger原子操作類
阿新 • • 發佈:2019-01-02
首先 , 測試一下正常程式碼
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包下除了提供的原子更新基本型別,還有原子更新資料、原子更新引用型別、原子更新欄位類,最常用的也就是原子更新基本型別了。