Java CAS原理

為了感謝支持我的朋友固歪!整理了一份Java高級架構(gòu)資料、Spring源碼分析胯努、Dubbo牢裳、Redis、Netty叶沛、zookeeper蒲讯、Spring cloud、分布式等資灰署。

本號專注Java源碼分析判帮。喜歡底層源碼的朋友可以來交流探討。交流群:818491202 驗(yàn)證:33


1. CAS是什么溉箕?

CAS全稱是Compare and Swap晦墙,即比較并交換,是通過原子指令來實(shí)現(xiàn)多線程的同步功能肴茄,將獲取存儲在內(nèi)存地址的原值和指定的內(nèi)存地址進(jìn)行比較晌畅,只有當(dāng)他們相等時,交換指定的預(yù)期值和內(nèi)存中的值寡痰,這個操作是原子操作抗楔,若不相等棋凳,則重新獲取存儲在內(nèi)存地址的原值。

2. CAS的流程

????? CAS是一種無鎖算法连躏,有3個關(guān)鍵操作數(shù)剩岳,內(nèi)存地址,舊的內(nèi)存中預(yù)期值入热,要更新的新值拍棕,當(dāng)內(nèi)存值和舊的內(nèi)存中預(yù)期值相等時,將內(nèi)存中的值更新為新值才顿。

3.樂觀鎖與悲觀鎖

CAS屬于樂觀鎖莫湘,樂觀鎖就是每次不加鎖而是假設(shè)沒有沖突而去完成某項(xiàng)操作,如果因?yàn)闆_突失敗就重試郑气,直到成功為止幅垮。

synchronized是悲觀鎖,被一個線程拿到鎖之后尾组,其他線程必須等待該線程釋放鎖忙芒,性能較差

二、AtomicInteger代碼演示

在java中讳侨,a++不是原子操作呵萨,一個簡單的a++操作涉及到三個操作,獲取變量a的內(nèi)存值跨跨,將變量a+1潮峦,將新值寫入內(nèi)存,這里涉及到了兩次內(nèi)存訪問勇婴,如果在多線程環(huán)境下忱嘹,那么會出現(xiàn)并發(fā)安全問題。

AtomicInteger是一個原子操作類耕渴,內(nèi)部采用的就是CAS無鎖算法拘悦。這里我們分析一下它的內(nèi)部實(shí)現(xiàn)。

AtomicInteger atomicInteger = new AtomicInteger(0);atomicInteger.getAndSet(1);復(fù)制代碼

這里的靜態(tài)代碼塊AtomicInteger對象初始化之前就執(zhí)行橱脸,獲取AtomicInteger對象value字段相對AtomicInteger對象的”起始地址”的偏移量础米,Java對象在內(nèi)存中存儲的布局可以分為三塊區(qū)域:對象頭(Header)、實(shí)例數(shù)據(jù)(Instance Data)和對齊填充(Padding)添诉,”起始地址”的偏移量即是對象頭的偏移量屁桑。

static {? ? try {? ? ? ? valueOffset = unsafe.objectFieldOffset? ? ? ? ? ? (AtomicInteger.class.getDeclaredField("value"));? ? } catch (Exception ex) { throw new Error(ex); }}復(fù)制代碼

public final int getAndSet(int newValue) {returnunsafe.getAndSetInt(this, valueOffset, newValue);}復(fù)制代碼

每次通過內(nèi)存地址(var2)先從內(nèi)存中獲取內(nèi)存中原值(var5),再循環(huán)將內(nèi)存中的原值(var5)與給定內(nèi)存地址(var2)相比較栏赴,如果相等則更新指定預(yù)期值(var4)掏颊,如果不相等則再重試直到成功為止,最后返回舊的內(nèi)存原值var5。

//var1為AtomicInteger對象乌叶,var2為內(nèi)存地址值盆偿,var4為指定的預(yù)期值public final int getAndSetInt(Object var1, long var2, int var4) {? ? int var5;do{//unsafe.getIntVolatile調(diào)用本地方法獲取內(nèi)存中值? ? ? ? var5 = this.getIntVolatile(var1, var2);? ? }while(!this.compareAndSwapInt(var1, var2, var5, var4));returnvar5;}復(fù)制代碼

三、弊端

1. ABA問題

CAS在操作的時候會檢查變量的值是否被更改過准浴,如果沒有則更新值事扭,但是帶來一個問題,最開始的值是A乐横,接著變成B求橄,最后又變成了A。經(jīng)過檢查這個值確實(shí)沒有修改過葡公,因?yàn)樽詈蟮闹颠€是A罐农,但是實(shí)際上這個值確實(shí)已經(jīng)被修改過了。為了解決這個問題催什,在每次進(jìn)行操作的時候加上一個版本號涵亏,每次操作的就是兩個值,一個版本號和某個值蒲凶,A——>B——>A問題就變成了1A——>2B——>3A气筋。在jdk中提供了AtomicStampedReference類解決ABA問題,用Pair這個內(nèi)部類實(shí)現(xiàn)旋圆,包含兩個屬性宠默,分別代表版本號和引用,在compareAndSet中先對當(dāng)前引用進(jìn)行檢查灵巧,再對版本號標(biāo)志進(jìn)行檢查搀矫,只有全部相等才更新值。

2. 只能保證一個共享變量的原子操作

多個共享變量操作時刻肄,循環(huán)CAS就無法保證操作的原子性瓤球,這個時候就可以用鎖。從java1.5開始肄方,JDK提供了AtomicReference類來保證引用對象之間的原子性,就可以把多個變量放在一個對象里來進(jìn)行CAS操作蹬癌。

3. 循環(huán)時間長CPU開銷較大

在并發(fā)量比較高的情況下权她,如果許多線程反復(fù)嘗試更新某一個變量,卻又一直更新不成功逝薪,循環(huán)往復(fù)隅要,會給CPU帶來很大的壓力。

關(guān)注公眾號領(lǐng)資料

搜索公眾號【Java耕耘者】,回復(fù)【Java】董济,即可獲取大量優(yōu)質(zhì)電子書和一份Java高級架構(gòu)資料步清、Spring源碼分析、Dubbo、Redis廓啊、Netty欢搜、zookeeper、Spring cloud谴轮、分布式等視頻資料

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末炒瘟,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子第步,更是在濱河造成了極大的恐慌疮装,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件粘都,死亡現(xiàn)場離奇詭異廓推,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)翩隧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進(jìn)店門樊展,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人鸽心,你說我怎么就攤上這事滚局。” “怎么了顽频?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵藤肢,是天一觀的道長。 經(jīng)常有香客問我糯景,道長嘁圈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任蟀淮,我火速辦了婚禮最住,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘怠惶。我一直安慰自己涨缚,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布策治。 她就那樣靜靜地躺著脓魏,像睡著了一般。 火紅的嫁衣襯著肌膚如雪通惫。 梳的紋絲不亂的頭發(fā)上茂翔,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天,我揣著相機(jī)與錄音履腋,去河邊找鬼珊燎。 笑死惭嚣,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的悔政。 我是一名探鬼主播晚吞,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼卓箫!你這毒婦竟也來了载矿?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤烹卒,失蹤者是張志新(化名)和其女友劉穎闷盔,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體旅急,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡逢勾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了藐吮。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片溺拱。...
    茶點(diǎn)故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖谣辞,靈堂內(nèi)的尸體忽然破棺而出迫摔,到底是詐尸還是另有隱情,我是刑警寧澤泥从,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布句占,位于F島的核電站,受9級特大地震影響躯嫉,放射性物質(zhì)發(fā)生泄漏纱烘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一祈餐、第九天 我趴在偏房一處隱蔽的房頂上張望擂啥。 院中可真熱鬧,春花似錦帆阳、人聲如沸哺壶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽山宾。三九已至,卻和暖如春芭逝,著一層夾襖步出監(jiān)牢的瞬間塌碌,已是汗流浹背渊胸。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工旬盯, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓胖翰,卻偏偏與公主長得像接剩,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子萨咳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評論 2 354

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

  • 引用地址 java.util.concurrent包完全建立在CAS之上的懊缺,沒有CAS就不會有此包∨嗨可見CAS的重...
    Lisy_閱讀 725評論 0 14
  • 一鹃两、線程狀態(tài)轉(zhuǎn)換新建(New)可運(yùn)行(Runnable)阻塞(Blocking)無限期等待(Waiting)限期等...
    達(dá)微閱讀 586評論 1 2
  • 【舊知】 今天讀《學(xué)習(xí)力》的內(nèi)容是堅(jiān)持21天打卡和夢想清單,看完后我才知道為什么我堅(jiān)持的21天為什么會沒有改變舀凛,寫...
    獅子吃檸檬閱讀 219評論 2 0
  • 三思而行 今天的課程題目是俊扳,理念變革與管理創(chuàng)新,浙江大學(xué)余瀟楓教授講授猛遍,有幸聽了他的一天課馋记,獲益匪淺。 課程內(nèi)容很...
    西風(fēng)瘦馬78閱讀 285評論 0 1
  • 光陰似箭懊烤,日月如梭梯醒,一個學(xué)期轉(zhuǎn)瞬即過。在這一年里腌紧,我學(xué)到很多茸习,不僅僅在教學(xué)上,更多的是在教學(xué)管理上寄啼。這才發(fā)現(xiàn)逮光,...
    康樂沐沐閱讀 1,303評論 2 14