教育行業(yè)A股IPO第一股(股票代碼 003032)

全國(guó)咨詢(xún)/投訴熱線(xiàn):400-618-4000

Java培訓(xùn):CAS原子指令相關(guān)知識(shí)

更新時(shí)間:2022年09月29日14時(shí)42分 來(lái)源:傳智教育 瀏覽次數(shù):

好口碑IT培訓(xùn)

  CAS(Compare and Swap),即比較并替換,是用于實(shí)現(xiàn)多線(xiàn)程同步的原子指令,是用于實(shí)現(xiàn)多線(xiàn)程同步的原子指令。

  執(zhí)行函數(shù):CAS(V,E,N)

  其包含3個(gè)參數(shù):

  · V表示要更新的變量

  · E表示預(yù)期值

  · N表示新值

  假定有兩個(gè)操作A和B,如果從執(zhí)行A的線(xiàn)程來(lái)看,當(dāng)另一個(gè)線(xiàn)程執(zhí)行B時(shí),要么將B全部執(zhí)行完,要么完全不執(zhí)行B,那么A和B對(duì)彼此來(lái)說(shuō)是原子的。

  實(shí)現(xiàn)原子操作可以使用鎖,鎖機(jī)制,滿(mǎn)足基本的需求是沒(méi)有問(wèn)題的了,但是有的時(shí)候我們的需求并非這么簡(jiǎn)單,我們需要更有效,更加靈活的機(jī)制,synchronized關(guān)鍵字是基于阻塞的鎖機(jī)制,也就是說(shuō)當(dāng)一個(gè)線(xiàn)程擁有鎖的時(shí)候,訪(fǎng)問(wèn)同一資源的其它線(xiàn)程需要等待,直到該線(xiàn)程釋放鎖。

  這里會(huì)有些問(wèn)題:首先,如果被阻塞的線(xiàn)程優(yōu)先級(jí)很高很重要怎么辦?其次,如果獲得鎖的線(xiàn)程一直不釋放鎖怎么辦?(這種情況是非常糟糕的)。還有一種情況,如果有大量的線(xiàn)程來(lái)競(jìng)爭(zhēng)資源,那CPU將會(huì)花費(fèi)大量的時(shí)間和資源來(lái)處理這些競(jìng)爭(zhēng),同時(shí),還有可能出現(xiàn)一些例如死鎖之類(lèi)的情況,最后,其實(shí)鎖機(jī)制是一種比較粗糙,粒度比較大的機(jī)制,相對(duì)于像計(jì)數(shù)器這樣的需求有點(diǎn)兒過(guò)于笨重。

  實(shí)現(xiàn)原子操作還可以使用當(dāng)前的處理器基本都支持CAS的指令,只不過(guò)每個(gè)廠(chǎng)家所實(shí)現(xiàn)的算法并不一樣,每一個(gè)CAS操作過(guò)程都包含三個(gè)運(yùn)算符:一個(gè)內(nèi)存地址V,一個(gè)期望的值A(chǔ)和一個(gè)新值B,操作的時(shí)候如果這個(gè)地址上存放的值等于這個(gè)期望的值A(chǔ),則將地址上的值賦為新值B,否則不做任何操作。

  CAS的基本思路就是,如果這個(gè)地址上的值和期望的值相等,則給其賦予新值,否則不做任何事兒,但是要返回原值是多少。循環(huán)CAS就是在一個(gè)循環(huán)里不斷的做cas操作,直到成功為止。

  CAS是怎么實(shí)現(xiàn)線(xiàn)程的安全呢?語(yǔ)言層面不做處理,我們將其交給硬件—CPU和內(nèi)存,利用CPU的多處理能力,實(shí)現(xiàn)硬件層面的阻塞,再加上volatile變量的特性即可實(shí)現(xiàn)基于原子操作的線(xiàn)程安全。

  CPU指令對(duì)CAS的支持

  或許我們可能會(huì)有這樣的疑問(wèn),假設(shè)存在多個(gè)線(xiàn)程執(zhí)行CAS操作并且CAS的步驟很多,有沒(méi)有可能在判斷V和E相同后,正要賦值時(shí),切換了線(xiàn)程,更改了值。造成了數(shù)據(jù)不一致呢?答案是否定的。

  因?yàn)镃AS是一種系統(tǒng)原語(yǔ),原語(yǔ)屬于操作系統(tǒng)用語(yǔ)范疇,是由若干條指令組成的,用于完成某個(gè)功能的一個(gè)過(guò)程,并且原語(yǔ)的執(zhí)行必須是連續(xù)的,在執(zhí)行過(guò)程中不允許被中斷,也就是說(shuō)CAS是一條CPU的原子指令,不會(huì)造成所謂的數(shù)據(jù)不一致問(wèn)題。

  悲觀(guān)鎖,樂(lè)觀(guān)鎖

  說(shuō)到CAS,不得不提到兩個(gè)專(zhuān)業(yè)詞語(yǔ):悲觀(guān)鎖,樂(lè)觀(guān)鎖。我們先來(lái)看看什么是悲觀(guān)鎖,什么是樂(lè)觀(guān)鎖。

  悲觀(guān)鎖顧名思義,就是比較悲觀(guān)的鎖,總是假設(shè)最壞的情況,每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人會(huì)修改,所以每次在拿數(shù)據(jù)的時(shí)候都會(huì)上鎖,這樣別人想拿這個(gè)數(shù)據(jù)就會(huì)阻塞直到它拿到鎖(共享資源每次只給一個(gè)線(xiàn)程使用,其它線(xiàn)程阻塞,用完后再把資源轉(zhuǎn)讓給其它線(xiàn)程)。傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù)里邊就用到了很多這種鎖機(jī)制,比如行鎖,表鎖等,讀鎖,寫(xiě)鎖等,都是在做操作之前先上鎖。Java中synchronized和ReentrantLock等獨(dú)占鎖就是悲觀(guān)鎖思想的實(shí)現(xiàn)。

  而樂(lè)觀(guān)鎖反之,總是假設(shè)最好的情況,每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人不會(huì)修改,所以不會(huì)上鎖,但是在更新的時(shí)候會(huì)判斷一下在此期間別人有沒(méi)有去更新這個(gè)數(shù)據(jù),可以使用版本號(hào)機(jī)制和CAS算法實(shí)現(xiàn)。樂(lè)觀(guān)鎖適用于多讀的應(yīng)用類(lèi)型,這樣可以提高吞吐量,像數(shù)據(jù)庫(kù)提供的類(lèi)似于write_condition機(jī)制,其實(shí)都是提供的樂(lè)觀(guān)鎖。我們今天講的CAS就是樂(lè)觀(guān)鎖。

  由于CAS操作屬于樂(lè)觀(guān)派,它總認(rèn)為自己可以成功完成操作,當(dāng)多個(gè)線(xiàn)程同時(shí)使用CAS操作一個(gè)變量時(shí),只有一個(gè)會(huì)勝出,并成功更新,其余均會(huì)失敗,但失敗的線(xiàn)程并不會(huì)被掛起,僅是被告知失敗,并且允許再次嘗試,當(dāng)然也允許失敗的線(xiàn)程放棄操作?;谶@樣的原理,CAS操作即使沒(méi)有鎖,同樣知道其他線(xiàn)程對(duì)共享資源操作影響,并執(zhí)行相應(yīng)的處理措施。同時(shí)從這點(diǎn)也可以看出,由于無(wú)鎖操作中沒(méi)有鎖的存在,因此不可能出現(xiàn)死鎖的情況,也就是說(shuō)無(wú)鎖操作天生免疫死鎖。

  CAS 的優(yōu)點(diǎn)

  非阻塞的輕量級(jí)樂(lè)觀(guān)鎖, 通過(guò)CPU指令實(shí)現(xiàn), 在資源競(jìng)爭(zhēng)不激烈的情況下性能高, 相比synchronize重量級(jí)悲觀(guān)鎖, synchronize有復(fù)雜的加鎖, 解鎖和喚醒線(xiàn)程操作。

0 分享到:
和我們?cè)诰€(xiàn)交談!