無鎖算法——CAS原理

一腊尚、無鎖算法

CAS(比較與交換喜每,Compare and swap) 是一種有名的無鎖算法间护。無鎖編程企蹭,即不使用鎖的情況下實(shí)現(xiàn)多線程之間的變量同步白筹,也就是在沒有線程被阻塞的情況下實(shí)現(xiàn)變量的同步,所以也叫非阻塞同步(Non-blocking Synchronization)练对。實(shí)現(xiàn)非阻塞同步的方案稱為“無鎖編程算法”( Non-blocking algorithm)遍蟋。?

相對應(yīng)的,獨(dú)占鎖是一種悲觀鎖螟凭,synchronized就是一種獨(dú)占鎖虚青,它假設(shè)最壞的情況,并且只有在確保其它線程不會造成干擾的情況下執(zhí)行螺男,會導(dǎo)致其它所有需要鎖的線程掛起棒厘,等待持有鎖的線程釋放鎖。?

使用lock實(shí)現(xiàn)線程同步有很多缺點(diǎn):?

* 產(chǎn)生競爭時(shí)下隧,線程被阻塞等待奢人,無法做到線程實(shí)時(shí)響應(yīng)。?

* dead lock淆院,死鎖何乎。?

* live lock。?

* 優(yōu)先級翻轉(zhuǎn)土辩。?

* 使用不當(dāng)支救,造成性能下降。?

當(dāng)然在部分情況下拷淘,目前來看各墨,無鎖編程并不能替代 lock。

二启涯、實(shí)現(xiàn)級別

非同步阻塞的實(shí)現(xiàn)可以分成三個(gè)級別:wait-free/lock-free/obstruction-free贬堵。?

wait-free?

是最理想的模式,整個(gè)操作保證每個(gè)線程在有限步驟下完成结洼。?

保證系統(tǒng)級吞吐(system-wide throughput)以及無線程饑餓黎做。?

截止2011年,沒有多少具體的實(shí)現(xiàn)松忍。即使實(shí)現(xiàn)了引几,也需要依賴于具體CPU。?

lock-free?

允許個(gè)別線程饑餓挽铁,但保證系統(tǒng)級吞吐伟桅。確保至少有一個(gè)線程能夠繼續(xù)執(zhí)行。?

wait-free的算法必定也是lock-free的情臭。?

obstruction-free?

在任何時(shí)間點(diǎn)芒炼,一個(gè)線程被隔離為一個(gè)事務(wù)進(jìn)行執(zhí)行(其他線程suspended)癌瘾,并且在有限步驟內(nèi)完成。在執(zhí)行過程中盖腕,一旦發(fā)現(xiàn)數(shù)據(jù)被修改(采用時(shí)間戳、版本號)浓镜,則回滾溃列。也叫做樂觀鎖,即樂觀并發(fā)控制(OOC)膛薛。事務(wù)的過程是:1讀取听隐,并寫時(shí)間戳;2準(zhǔn)備寫入哄啄,版本校驗(yàn)雅任;3校驗(yàn)通過則寫入,校驗(yàn)不通過咨跌,則回滾沪么。?

lock-free必定是obstruction-free的。

三锌半、CAS算法

CAS(比較與交換禽车,Compare and swap) 是一種有名的無鎖算法。CAS, CPU指令刊殉,在大多數(shù)處理器架構(gòu)殉摔,包括IA32、Space中采用的都是CAS指令冗澈,CAS的語義是“我認(rèn)為V的值應(yīng)該為A钦勘,如果是,那么將V的值更新為B亚亲,否則不修改并告訴V的值實(shí)際為多少”彻采,CAS是項(xiàng) 樂觀鎖 技術(shù),當(dāng)多個(gè)線程嘗試使用CAS同時(shí)更新同一個(gè)變量時(shí)捌归,只有其中一個(gè)線程能更新變量的值肛响,而其它線程都失敗,失敗的線程并不會被掛起惜索,而是被告知這次競爭中失敗特笋,并可以再次嘗試。CAS有3個(gè)操作數(shù)巾兆,內(nèi)存值V猎物,舊的預(yù)期值A(chǔ)虎囚,要修改的新值B。當(dāng)且僅當(dāng)預(yù)期值A(chǔ)和內(nèi)存值V相同時(shí)蔫磨,將內(nèi)存值V修改為B淘讥,否則什么都不做。?

java.util.concurrent.atomic中的AtomicXXX堤如,都使用了這些底層的JVM支持為數(shù)字類型的引用類型提供一種高效的CAS操作蒲列,而在java.util.concurrent中的大多數(shù)類在實(shí)現(xiàn)時(shí)都直接或間接的使用了這些原子變量類,這些原子變量都調(diào)用了 sun.misc.Unsafe 類庫里面的 CAS算法搀罢,用CPU指令來實(shí)現(xiàn)無鎖自增蝗岖,JDK源碼:

public final int getAndIncrement() {

? ? ? ? for (;;) {?

? ? ? ? ? ? int current = get();?

? ? ? ? ? ? int next = current + 1;?

? ? ? ? ? ? if (compareAndSet(current, next))?

? ? ? ? ? ? ? ? return current;?

? ? ? ? }?

}??

public final boolean compareAndSet(int expect, int update) {?

? ? return unsafe.compareAndSwapInt(this, valueOffset, expect, update);?

}

因而在大部分情況下,java中使用Atomic包中的incrementAndGet的性能比用synchronized高出幾倍榔至。

四抵赢、ABA問題

thread1意圖對val=1進(jìn)行操作變成2,cas(val,1,2)洛退。?

thread1先讀取val=1瓣俯;thread1被搶占(preempted),讓thread2運(yùn)行兵怯。?

thread2 修改val=3彩匕,又修改回1。?

thread1繼續(xù)執(zhí)行媒区,發(fā)現(xiàn)期望值與“原值”(其實(shí)被修改過了)相同驼仪,完成CAS操作。?

使用CAS會造成ABA問題袜漩,特別是在使用指針操作一些并發(fā)數(shù)據(jù)結(jié)構(gòu)時(shí)绪爸。?

解決方案?

ABA?:添加額外的標(biāo)記用來指示是否被修改。?

從Java1.5開始JDK的atomic包里提供了一個(gè)類AtomicStampedReference來解決ABA問題宙攻。這個(gè)類的compareAndSet方法作用是首先檢查當(dāng)前引用是否等于預(yù)期引用奠货,并且當(dāng)前標(biāo)志是否等于預(yù)期標(biāo)志,如果全部相等座掘,則以原子方式將該引用和該標(biāo)志的值設(shè)置為給定的更新值递惋。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市溢陪,隨后出現(xiàn)的幾起案子萍虽,更是在濱河造成了極大的恐慌,老刑警劉巖形真,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件杉编,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)邓馒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進(jìn)店門嘶朱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人绒净,你說我怎么就攤上這事见咒。” “怎么了挂疆?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長下翎。 經(jīng)常有香客問我缤言,道長,這世上最難降的妖魔是什么视事? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任胆萧,我火速辦了婚禮,結(jié)果婚禮上俐东,老公的妹妹穿的比我還像新娘跌穗。我一直安慰自己,他們只是感情好虏辫,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布蚌吸。 她就那樣靜靜地躺著,像睡著了一般砌庄。 火紅的嫁衣襯著肌膚如雪羹唠。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天娄昆,我揣著相機(jī)與錄音佩微,去河邊找鬼。 笑死萌焰,一個(gè)胖子當(dāng)著我的面吹牛哺眯,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播扒俯,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼奶卓,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了陵珍?” 一聲冷哼從身側(cè)響起寝杖,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎互纯,沒想到半個(gè)月后瑟幕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年只盹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了辣往。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,503評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡殖卑,死狀恐怖站削,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情孵稽,我是刑警寧澤许起,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站菩鲜,受9級特大地震影響园细,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜接校,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一猛频、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蛛勉,春花似錦鹿寻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至皿淋,卻和暖如春招刹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背窝趣。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工疯暑, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人哑舒。 一個(gè)月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓妇拯,卻偏偏與公主長得像,于是被迫代替她去往敵國和親洗鸵。 傳聞我的和親對象是個(gè)殘疾皇子越锈,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評論 2 359

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

  • 鎖的代價(jià) 鎖是用來做并發(fā)最簡單的方式,當(dāng)然其代價(jià)也是最高的膘滨。內(nèi)核態(tài)的鎖在鎖的時(shí)候需要操作系統(tǒng)進(jìn)行一次上下文切換甘凭,加...
    cgw丶閱讀 3,242評論 0 5
  • Java8張圖 11、字符串不變性 12火邓、equals()方法丹弱、hashCode()方法的區(qū)別 13德撬、...
    Miley_MOJIE閱讀 3,709評論 0 11
  • 不講語言特性,只從工程角度出發(fā)躲胳,個(gè)人覺得C++標(biāo)準(zhǔn)委員會在C++11中對多線程庫的引入是有史以來做得最人道的一件事...
    stidio閱讀 13,330評論 0 11
  • 郵箱里客戶詢盤堆積成山 內(nèi)容良莠不齊 潛在目標(biāo)客戶蜓洪? 竊取行業(yè)信息? 高質(zhì)量合作客戶坯苹? 同行惡意競爭隆檀? 業(yè)務(wù)員早已...
    貿(mào)立方閱讀 344評論 0 0
  • Stack Overflow 的數(shù)據(jù)科學(xué)家 David Robinson 發(fā)現(xiàn),軟件行業(yè)的分工讓不同發(fā)達(dá)地區(qū)的程序...
    老牛哥兒閱讀 463評論 0 0