AtomicInteger 可以算是一類Automic類的代表修陡,在多線程的運行環(huán)境中损姜,提供原子操作。
AutomicInteger 可以讓多線程程序更新一個int 值,但是保證更新的原子性贬媒,普通的Integer 更新的時候分為3步:
- 讀取int值
- 計算更新后的int值
- 將更新后的int值寫回到內(nèi)存中
由于這3步不是一個原子操作,所以多線程的更新的時候肘习,就會出現(xiàn)線程a讀取的值為1际乘,并且根據(jù)1計算,但是在真正寫入之前漂佩,這個值已經(jīng)被b寫成了別的值脖含,這就會導(dǎo)致程序的錯亂。這也就是為什么我們要用AutomicInteger的原因投蝉。
使用實例:
AtomicInteger ai = new AtomicInteger(0);
ai.addAndGet(5); // 5
ai.getAndAdd(1); // 5
ai.get(); // 6
原理
AtomicInteger內(nèi)有一個Unsafe類养葵,支持CAS操作,而且類內(nèi)部還有一個value類(使用volatile保證內(nèi)存更新可見性)記錄對象值瘩缆。
CAS是Compare And Swap 的縮寫关拒,也就是在更新前會比較目標對象的值是不是所期望的值,也就是一次更新需要2個值,期望的原來的值和要更新成的值夏醉。
例如: 將變量a 從1更新為2
Unsafe 是通過調(diào)用C++代碼調(diào)用CPU指令達到原子性的操作爽锥,具體內(nèi)部實現(xiàn)參看下面代碼實例(給一個atomicInterger加一個值):
// var2 是變量內(nèi)存地址, var4為要增加的值
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
var5 = this.getIntVolatile(var1, var2); // var5 拿到當前值
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
return var5;
}
通過上面代碼可以看出畔柔,如果沒有更新成功氯夷,這個循環(huán)會一直進行。
ABA問題
上述的AtomicInteger原理雖然可以解決多線程并發(fā)的問題靶擦,但是并不完美腮考,會有ABA的問題出現(xiàn)。
具體見 ABA
ABA的問題本質(zhì)是因為CAS的方式是用樂觀鎖實現(xiàn)玄捕,不會鎖住共享變量踩蔚,是一種非阻塞的同步機制。
但是卻沒有大多數(shù)樂觀鎖的唯一遞增version字段來保證更新的順序枚粘,所以會出現(xiàn)ABA問題馅闽。