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、函數列表
三、存儲結構
- 支持併發的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類。