AtomicInteger

AtomicInteger閱讀筆記

問題

1、什麼是原子操作?

  • 一個事務(transaction)中的所有操作,要麼全部完成,要麼全部不完成,不會結束在中間某個環節。事務在執行過程中發生錯誤,會被回滾(Rollback)到事務開始前的狀態,就像這個事務從來沒有執行過一樣

2、什麼是可見性?

  • 可見性是指當多個線程訪問同一個變量時,一個線程修改了這個變量的值,其他線程能夠立即看得到修改的值。

3、AtomicInteger通過什麼實現原子操作?

  • 通過Unsafe原子工具類來實現原子操作

4、AtomicInteger有什麼缺點?

  • 有ABA問題,且自旋消耗CPU性能

一、簡介

優點:

  • CAS樂觀鎖,性能較強,利用CPU自身的特性保證原子性,即CPU的指令集封裝CompareAndSwap兩個操作爲一個指令來保證原子性。
  • 適合讀多寫少模式。

缺點:

  • 自旋,消耗CPU性能,所以寫的操作較多推薦sync(悲觀鎖)
  • 僅適合簡單的運算,否則會 產生ABA問題,自旋的時候,別的線程可能更改value,然後又更改回來,此時需要加版本號解決,JDK提供了AtomicStampedReference和AtomicMarkableReference解決ABA問題,提供基本數據類型和引用數據類型版本號支持

二、繼承關係圖

1、繼承Number抽象類、實現Serializable接口

2、函數列表
C:\Users\86134\AppData\Local\Temp\1577238960051.png

三、存儲結構

  • 支持併發的Integer存儲結構,大部分都是final方法

四、源碼分析

內部類

屬性

  • Unsafe:工具
  • value:int值
  • valueOffset:內存偏移地址

構造

  • public AtomicInteger()
    • 實例化AtomicInteger
  • public AtomicInteger(int initialValue) {value = initialValue;}
    • 實例化AtomicInteger 且初始化value。

主要方法

  • public final int getAndAdd(int delta){ return unsafe.getAndAddInt(this, valueOffset, delta);}
    • 返回當前value,在內存中對value進行加delta,
  • public final int addAndGet(int delta){ return unsafe.getAndAddInt(this, valueOffset, delta) + delta;}
    • 在內存中對value進行加delta,然後返回原value+delta的和。
  • public final int getAndDecrement(){ return unsafe.getAndAddInt(this, valueOffset, -1);}
    • 返回當前value,然後對value-1,類似i–;
  • public final int getAndIncrement() { return unsafe.getAndAddInt(this, valueOffset, 1);}
    • 返回當然value,然後對value+1,類似i++;
  • public final int decrementAndGet() {return unsafe.getAndAddInt(this, valueOffset, -1) - 1;}
    • 在內存中對value進行-1,然後返回的值,類似–i;
  • public final int incrementAndGet() {return unsafe.getAndAddInt(this,valueOffset, 1) + 1;}
    • 在內存中對value進行+1,然後返回新的值,類似++i;
  • public final int getAndSet(int newValue) { return unsafe.getAndSetInt(this, valueOffset, newValue);}
    • 返回當前value,然後把value更新爲newValue,採用cas
  • public final void set(int newValue) {value = newValue;}
    • 更新value爲newValue。立即修改舊值,別的線程可以立馬看到新值
  • public final void lazySet(int newValue){unsafe.putOrderedInt(this,valueOffset, newValue);}
    • 更新value爲newValue。不能保證其他線程能立即看到修改的值,但最終會看到

補充

//獲取Unsafe工具
private static final Unsafe unsafe = Unsafe.getUnsafe();
//value值在AtomicInteger對象中的偏移量,用於讀寫操作
private static final long valueOffset;
static {
    try {
        //初始化valueOffset
        //使用反射獲得value字段的Field,然後調用unsafe工具類的objectFieldOffset(獲取非靜態屬性在對象中的偏移量)。
        valueOffset = unsafe.objectFieldOffset
            (AtomicInteger.class.getDeclaredField("value"));
    } catch (Exception ex) { throw new Error(ex); }
}

//Unsafe包中的getAndAddInt
public final int getAndAddInt(Object var1, long var2, int var4) {
    int var5;
    do {
        var5 = this.getIntVolatile(var1, var2);//使用volatile方式獲取值
    } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));//循環更新值,失敗繼續

    return var5;
}

五、總結

主要大量運用了Unsafe類。

發佈了48 篇原創文章 · 獲贊 17 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章