CAS算法AtomicInteger

http://www.reibang.com/p/cec71079acdf (相當(dāng)完整)

題一:java中的CAS是什么于游?

問題二:為什么要使用CAS?

問題三:CAS使用中需要注意什么問題?

這里以提問的方式引出話題,下面帶大家慢慢了解CAS真椿。

1.CAS的含義

CAS是compare and swap的縮寫,即我們所說的比較交換。cas是一種基于鎖的操作,而且是樂觀鎖斟冕。在java中鎖分為樂觀鎖和悲觀鎖。悲觀鎖是將資源鎖住缅阳,等一個(gè)之前獲得鎖的線程釋放鎖之后磕蛇,下一個(gè)線程才可以訪問。而樂觀鎖采取了一種寬泛的態(tài)度十办,通過某種方式不加鎖來處理資源秀撇,比如通過給記錄加version來獲取數(shù)據(jù),性能較悲觀鎖有很大的提高向族。

CAS 操作包含三個(gè)操作數(shù) —— 內(nèi)存位置(V)呵燕、預(yù)期原值(A)和新值(B)。如果內(nèi)存地址里面的值和A的值是一樣的件相,那么就將內(nèi)存里面的值更新成B再扭。CAS是通過無限循環(huán)來獲取數(shù)據(jù)的,若果在第一輪循環(huán)中夜矗,a線程獲取地址里面的值被b線程修改了泛范,那么a線程需要自旋,到下次循環(huán)才有可能機(jī)會(huì)執(zhí)行紊撕。

2.CAS的問題

①.CAS容易造成ABA問題敦跌。一個(gè)線程a將數(shù)值改成了b,接著又改成了a逛揩,此時(shí)CAS認(rèn)為是沒有變化,其實(shí)是已經(jīng)變化過了麸俘,而這個(gè)問題的解決方案可以使用版本號標(biāo)識(shí)辩稽,每操作一次version加1。在java5中从媚,已經(jīng)提供了AtomicStampedReference來解決問題逞泄。

②.CAS造成CPU利用率增加。之前說過了CAS里面是一個(gè)循環(huán)判斷的過程,如果線程一直沒有獲取到狀態(tài)喷众,cpu資源會(huì)一直被占用各谚。

3.看AutoInteger的實(shí)現(xiàn)源碼

其實(shí)AutoInteger就是使用了CAS來實(shí)現(xiàn)加1,我們知道如果有一個(gè)共享變量count=1,開5個(gè)線程到千,每個(gè)線程加20次昌渤,結(jié)果一般來說都會(huì)小于100.

@Test
public void test20() throws InterruptedException {
for (int i = 1; i <= 5; i++) {
MyThrend thrend = new MyThrend("thead" + i);
Thread thread = new Thread(thrend);
thread.start();
}
Thread.sleep(2000);
System.out.println(MyCount1.count);
}

static class MyThrend implements Runnable {
private String name;
MyThrend(String threadName) {
this.name = threadName;
}

@Override
public void run() {
    for (int i=0;i<20;i++)
    MyCount1.count++;
}

}

private static class MyCount1 {
static int count = 0;
}

結(jié)果78

現(xiàn)在修改一個(gè)代碼,將int變成AtomicInteger

@Test
public void test20() throws InterruptedException {
for (int i = 1; i <= 5; i++) {
MyThrend thrend = new MyThrend("thead" + i);
Thread thread = new Thread(thrend);
thread.start();
}
Thread.sleep(2000);
System.out.println(MyCount.count.get());
}

static class MyThrend implements Runnable {
private String name;
MyThrend(String threadName) {
this.name = threadName;
}

@Override
public void run() {
    for (int i=0;i<20;i++)
    MyCount.count.getAndIncrement();  //加1方法
}

}

private static class MyCount {
static AtomicInteger count = new AtomicInteger(0);
}

每次結(jié)果都是100憔四,怎么做到的呢膀息?這里是沒有直接加鎖的,看源碼了赵。

public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1); //第一個(gè)參數(shù)當(dāng)前對象地址潜支,第二個(gè)參數(shù)數(shù)據(jù)偏移量,第三個(gè)參數(shù)每次指定默認(rèn)加1
}

public final int getAndAddInt(Object var1, long var2, int var4) { //這個(gè)方法使用的就是CAS,核心在于循環(huán)比較內(nèi)存里面的值和當(dāng)前值是否相等柿汛,如果相等就用新值覆蓋
int var5;
do {
var5 = this.getIntVolatile(var1, var2); //如果a冗酿,b線程同時(shí)執(zhí)行這個(gè)方法,a線程拿到值1后cpu執(zhí)行時(shí)間到了掛起络断,b開始執(zhí)行裁替,也拿到1,但是沒有掛起妓羊,接著將值變成了2
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4)); //這個(gè)時(shí)候a線程恢復(fù)執(zhí)行胯究,去比較的時(shí)候發(fā)現(xiàn)手上的1 和內(nèi)存里面的值2不等,這個(gè)時(shí)候他要進(jìn)行下一個(gè)循環(huán)躁绸,看出來了占用cpu吧
return var5;
}

AtomicInteger裕循,AtomicLong,AtomicBoolean.....都在java.util.current.atomic包下面,采用了CAS機(jī)制來實(shí)現(xiàn)加鎖净刮,里面具體方法就不看了剥哑,留給大家后續(xù)研究!
————————————————
版權(quán)聲明:本文為CSDN博主「歸海一刀之漁舟唱晚」的原創(chuàng)文章淹父,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議株婴,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/u011381576/article/details/79922538

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末暑认,一起剝皮案震驚了整個(gè)濱河市困介,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蘸际,老刑警劉巖座哩,帶你破解...
    沈念sama閱讀 222,464評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異粮彤,居然都是意外死亡根穷,警方通過查閱死者的電腦和手機(jī)姜骡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來屿良,“玉大人圈澈,你說我怎么就攤上這事〕揪澹” “怎么了康栈?”我有些...
    開封第一講書人閱讀 169,078評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長褥伴。 經(jīng)常有香客問我谅将,道長,這世上最難降的妖魔是什么重慢? 我笑而不...
    開封第一講書人閱讀 59,979評論 1 299
  • 正文 為了忘掉前任饥臂,我火速辦了婚禮,結(jié)果婚禮上似踱,老公的妹妹穿的比我還像新娘隅熙。我一直安慰自己,他們只是感情好核芽,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,001評論 6 398
  • 文/花漫 我一把揭開白布囚戚。 她就那樣靜靜地躺著,像睡著了一般轧简。 火紅的嫁衣襯著肌膚如雪驰坊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,584評論 1 312
  • 那天哮独,我揣著相機(jī)與錄音拳芙,去河邊找鬼。 笑死皮璧,一個(gè)胖子當(dāng)著我的面吹牛舟扎,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播悴务,決...
    沈念sama閱讀 41,085評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼睹限,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了讯檐?” 一聲冷哼從身側(cè)響起羡疗,我...
    開封第一講書人閱讀 40,023評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎别洪,沒想到半個(gè)月后叨恨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,555評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蕉拢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,626評論 3 342
  • 正文 我和宋清朗相戀三年特碳,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晕换。...
    茶點(diǎn)故事閱讀 40,769評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡午乓,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出闸准,到底是詐尸還是另有隱情益愈,我是刑警寧澤,帶...
    沈念sama閱讀 36,439評論 5 351
  • 正文 年R本政府宣布夷家,位于F島的核電站蒸其,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏库快。R本人自食惡果不足惜摸袁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,115評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望义屏。 院中可真熱鬧靠汁,春花似錦、人聲如沸闽铐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽兄墅。三九已至踢星,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間隙咸,已是汗流浹背沐悦。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留扎瓶,地道東北人所踊。 一個(gè)月前我還...
    沈念sama閱讀 49,191評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像概荷,于是被迫代替她去往敵國和親秕岛。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,781評論 2 361

推薦閱讀更多精彩內(nèi)容