CAS:CompareAndSwap,是一種原子操作缭嫡,用于在多線程環(huán)境中保證不被打斷的數(shù)據(jù)交換操作喂很,用舊值和主內(nèi)存中的值做比較惜颇,如果相同則講舊值替換成新值,Java中由sun.misc.UnSafe類實(shí)現(xiàn)CAS少辣。
AtomicInteger這個(gè)類在多線程環(huán)境下是線程安全的凌摄,它的getAndIncrement()方法能夠在多線程環(huán)境下安全地實(shí)現(xiàn)i++操作,以下是它的源碼,它調(diào)用了UnSafe類的getAndAddInt方法漓帅。
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;//定義一個(gè)新值
do {
var5 = this.getIntVolatile(var1, var2);//將val1對(duì)象在var2內(nèi)存地址的值賦給var5
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));//這里的compareAndSwapInt方法是將var1對(duì)象在var2內(nèi)存地址的值和var5比較锨亏,如果相同的話,var5設(shè)置為var5+var4忙干,并且這個(gè)返回返回true器予,跳出循環(huán)。如果舊值var5和內(nèi)存中的值不相同的話捐迫,則在while中一直循環(huán)乾翔,直至值相同為止
return var5;
}
CAS的缺點(diǎn):
- 如果舊值和內(nèi)存中的值一直不相等,會(huì)一直循環(huán)施戴,會(huì)給CPU帶來很大的開銷
- CAS只能對(duì)一個(gè)共享變量保證原子操作反浓,無法對(duì)多個(gè)共享變量保證原子操作
- ABA問題
ABA
什么是ABA?假設(shè)有兩個(gè)線程赞哗,分別叫T1和T2雷则,T1和T2分別從主內(nèi)存中拷貝一份變量,這個(gè)變量的值是A肪笋,T1和T2線程都要對(duì)變量A修改操作月劈,T2先作出修改,根據(jù)CAS原則藤乙,變量A在主內(nèi)存中的值還是A猜揪,所以A被修改成為B,緊接著T2線程又對(duì)B進(jìn)行修改湾盒,把B改成A湿右,T2線程完成任務(wù)诅妹,被掛起罚勾。然后T1線程修改變量的值,工作內(nèi)存的值和主內(nèi)存的值都是A吭狡,所以T1線程也可以修改這個(gè)變量尖殃,但是T1線程不知道該變量在它修改之前已經(jīng)被修改過了。
那么如何解決ABA問題划煮?
使用J.U.C包提供的AtomicStampedReference類送丰,用版本號(hào)來控制CAS。