Java多線程:CAS與java.util.concurrent.atomic

樂觀鎖與悲觀鎖

悲觀鎖

總是假設(shè)最壞的情況刻恭,每次獲取數(shù)據(jù)都認為別人會修改,所以拿數(shù)據(jù)時會上鎖,一直到釋放鎖不允許其他線程修改數(shù)據(jù)。Java中如synchronized和reentrantLock就是這種實現(xiàn)冰蘑。

樂觀鎖

總是假設(shè)最好的情況,每次去拿數(shù)據(jù)時都認為別人不會修改村缸,所以不上鎖祠肥,等更新數(shù)據(jù)時判斷一下在此期間是否有其他人更新過這個數(shù)據(jù),可以使用CAS算法實現(xiàn)梯皿。樂觀鎖適用于多讀少寫的應(yīng)用類型仇箱,可以大幅度提高吞吐量县恕。樂觀鎖的實現(xiàn)機制主要包括版本號機制(給數(shù)據(jù)加一個版本號,數(shù)據(jù)被修改版本號會加一剂桥,更新時讀取版本號忠烛,若讀取到的版本號和之前一致才更新,否則駁回)和CAS算法(下詳)权逗。

CAS算法

JDK5增加java.util.concurrent包美尸,其下類通過CAS算法實現(xiàn)了樂觀鎖實現(xiàn)。

CAS即compare and swap斟薇,是一種有名的無鎖算法师坎,即不使用鎖的情況下實現(xiàn)多線程之間的變量同步,也叫非阻塞同步堪滨。

CAS有三個操作數(shù)胯陋,內(nèi)存值V,舊的預(yù)期內(nèi)存值A(chǔ)袱箱,要修改的新值B遏乔,當且僅當A=V,才將內(nèi)存值V修改為B犯眠,否則不會執(zhí)行任何操作按灶。一般情況下CAS是一個自旋操作,即不斷重試筐咧。

CAS只能保證一個共享變量的原子操作鸯旁,當操作涉及跨多個共享變量時CAS無效。但可用AtomicReference來保證引用對象之間的原子性量蕊。

CAS開銷

CAS是CPU指令集的操作铺罢,只有一步的原子操作,所以非巢信冢快韭赘,但CAS的開銷主要在于cache miss問題。如圖

image

這是一個8核CPU系統(tǒng)势就,共有4個管芯泉瞻,每個管芯中有兩個CPU,每個CPU有cache苞冯,管芯內(nèi)有一個互聯(lián)模塊袖牙,讓管芯的兩個核可以互相通信。圖中的系統(tǒng)連接模塊可以讓四個管芯通信舅锄。例如鞭达,此時CPU0進行一個CAS操作,而該變量所在的緩存線在CPU7的高速緩存中,則流程如下:

  • CPU檢查本地緩存畴蹭,沒有找到緩存線坦仍。
  • 請求被轉(zhuǎn)發(fā)到CPU0和CPU1的互聯(lián)模塊,檢查CPU1的本地高速緩存叨襟,沒有找到緩存線繁扎。
  • 請求被轉(zhuǎn)發(fā)到系統(tǒng)互聯(lián)模塊,檢查其他三個管芯芹啥,得知緩存線在CPU6和CPU7所在的管芯中锻离。
  • 請求被轉(zhuǎn)發(fā)到CPU6和CPU7的互聯(lián)模塊,檢查這兩個CPU的高速緩存墓怀,在CPU7中找到緩存線汽纠。
  • CPU7將緩存線發(fā)給互聯(lián)模塊,并刷新自己的緩存線傀履。
  • CPU6和CPU7的互聯(lián)模塊將緩存線發(fā)送給系統(tǒng)互聯(lián)模塊虱朵。
  • 系統(tǒng)互聯(lián)模塊將緩存線發(fā)送給CPU0和CPU1的互聯(lián)模塊。
  • CPU0對高速緩存中的變量致性CAS操作钓账。

此外碴犬,資源競爭時,CAS會自旋(不成功就循環(huán)到成功)梆暮,

ABA問題

CAS一個常見問題是ABA問題服协,即變量V初次讀時是A值,被賦值時也是A值啦粹,但期間變量被賦值成B值,CAS會誤認為他從沒被修改過偿荷。JDK1.5后的AtomicStampedReference類提供了監(jiān)測ABA問題的能力,其中的compareAndSet方法首先檢查當前引用是否等于預(yù)期引用唠椭,并且當前標志等于預(yù)期標志跳纳,全部相等則以原子方式將該引用和該標志的值設(shè)置為給定的更新值。

CAS與synchronized

  • 資源競爭少時贪嫂,synchronized同步鎖進行線程阻塞寺庄,喚醒切換,用戶內(nèi)核態(tài)間切換力崇,浪費額外CPU資源斗塘,CAS基于硬件實現(xiàn),不進入內(nèi)核亮靴,不切換線程逛拱,操作自旋幾率小,CAS有更高的性能台猴。
  • 資源競爭嚴重時,CAS自旋概率較大,從而浪費更多的CPU資源饱狂,效率低于synchronized曹步。

java.util.concurrent.atomic

jdk1.5提供了一組原子類,由CAS對其實現(xiàn)休讳。其中的類可以分為四組:

  • AtomicBoolean讲婚,AtomicInteger,AtomicLong俊柔,AtomicReference
  • AtomicIntegerArray筹麸,AtomicLongArray
  • AtomicLongFieldUpdater,AtomicIntegerFieldUpdater雏婶,AtomicReferenceFieldUpdater
  • AtomicMarkableReference物赶,AtomicStampedReference,AtomicReferenceArray

其作用為對單一數(shù)據(jù)的操作實現(xiàn)原子化留晚,無需阻塞代碼酵紫,但訪問兩個或兩個以上的atomic變量或?qū)蝹€atomic變量進行2次或2次以上的操作被認為是需要同步的以便這些操作是一個原子操作。

AtomicBoolean, AtomicInteger, AtomicLong, AtomicReference

這四種類型用來處理Boolean错维,Integer, Long, 對象奖地,包含以下方法:

  • 構(gòu)造函數(shù),默認值分別為false, 0, 0, null赋焕。帶參數(shù)則參數(shù)為初始化數(shù)據(jù)参歹。
  • set()和get()方法,常規(guī)的設(shè)置/讀取值隆判,非原子操作犬庇。
  • lazySet(),設(shè)置值蜜氨,原子操作械筛。
  • getAndSet()相當于先使用get再set,但是是一個原子操作飒炎。
  • compareAndSet(expectedData, newData)埋哟,接受兩個參數(shù),若atomic內(nèi)數(shù)據(jù)和期望數(shù)據(jù)一致郎汪,則將新數(shù)據(jù)賦值給atomic數(shù)據(jù)返回true赤赊,否則不設(shè)置并返回false。
  • weakCompareAndSet(expectedData, newData)煞赢,與前者類似抛计,但更高效,不同的是可能會返回虛假的失敗照筑,不提供排序的保證吹截,最好用于五關(guān)于happens-before的程序瘦陈。

對于AtomicInteger, AtomicLong,還實現(xiàn)了getAndIncrement(),increateAndGet(),getAndDecreate(),decreateAndGet(),addAndGet()波俄,getAndAdd()方法晨逝,以實現(xiàn)加減法的原子操作。剩下部分代碼我還在閱讀中懦铺,不定期補充捉貌。

參考文獻

深入理解CAS算法原理
面試必備之樂觀鎖與悲觀鎖
Java之多線程 Atomic(原子的)
對 volatile、compareAndSet冬念、weakCompareAndSet 的一些思考

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末趁窃,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子急前,更是在濱河造成了極大的恐慌醒陆,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件叔汁,死亡現(xiàn)場離奇詭異统求,居然都是意外死亡,警方通過查閱死者的電腦和手機据块,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門码邻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人另假,你說我怎么就攤上這事像屋。” “怎么了边篮?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵己莺,是天一觀的道長。 經(jīng)常有香客問我戈轿,道長凌受,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任思杯,我火速辦了婚禮胜蛉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘色乾。我一直安慰自己誊册,他們只是感情好,可當我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布暖璧。 她就那樣靜靜地躺著案怯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪澎办。 梳的紋絲不亂的頭發(fā)上嘲碱,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天金砍,我揣著相機與錄音,去河邊找鬼麦锯。 笑死捞魁,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的离咐。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼奉件,長吁一口氣:“原來是場噩夢啊……” “哼宵蛀!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起县貌,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤术陶,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后煤痕,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體梧宫,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年摆碉,在試婚紗的時候發(fā)現(xiàn)自己被綠了塘匣。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡巷帝,死狀恐怖忌卤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情楞泼,我是刑警寧澤驰徊,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站堕阔,受9級特大地震影響棍厂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜超陆,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一产还、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧状您,春花似錦撩幽、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至瞧预,卻和暖如春屎债,著一層夾襖步出監(jiān)牢的瞬間仅政,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工盆驹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留圆丹,地道東北人。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓躯喇,卻偏偏與公主長得像辫封,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子廉丽,可洞房花燭夜當晚...
    茶點故事閱讀 44,611評論 2 353

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

  • java多線程里面volatile以及CAS都是比單純的鎖能提供更高性能的一種共享資源訪問機制倦微,在這里進行對其原理...
    VIPSHOP_FCS閱讀 9,310評論 2 14
  • CAS簡歷 CAS(Compare and swap)比較和替換是設(shè)計并發(fā)算法時用到的一種技術(shù) 。Compare ...
    classtag閱讀 4,152評論 2 37
  • Java8張圖 11正压、字符串不變性 12欣福、equals()方法、hashCode()方法的區(qū)別 13焦履、...
    Miley_MOJIE閱讀 3,701評論 0 11
  • 鎖的代價 鎖是用來做并發(fā)最簡單的方式拓劝,當然其代價也是最高的。內(nèi)核態(tài)的鎖在鎖的時候需要操作系統(tǒng)進行一次上下文切換嘉裤,加...
    cgw丶閱讀 3,237評論 0 5
  • 三個階段依賴期獨立期互賴期品德誠信郑临、謙虛、忠誠价脾、節(jié)欲牧抵、勇敢、公正侨把、耐心犀变、樸素人際關(guān)系禮貌、誠實秋柄、仁慈获枝、信用增強人際...
    用戶高盧總督閱讀 648評論 0 1