每日一博 - CAS(Compare-And-Swap)原理剖析
文章目錄
- What's CAS & sun.misc.Unsafe
- CAS & sun.misc.Unsafe
- 以AtomicInteger為例底層原理剖析
- CAS缺點(diǎn)
- ABA 問(wèn)題
What’s CAS & sun.misc.Unsafe
全稱(chēng) Compare-And-Swap , 主要實(shí)現(xiàn)的功能是和內(nèi)存中的某個(gè)位置的值進(jìn)行比較判斷是否為預(yù)期值,如果是預(yù)期值則更改為新值, 整個(gè)過(guò)程具有原子性。
CAS & sun.misc.Unsafe
CAS屬于CPU并發(fā)原語(yǔ)
CAS是一種系統(tǒng)原語(yǔ),原語(yǔ)屬于操作系統(tǒng)應(yīng)用范疇,是由若干條指令組成,用于完成某個(gè)功能的一個(gè)過(guò)程,并且原語(yǔ)的執(zhí)行必須是連續(xù)的,在執(zhí)行過(guò)程中不允許被中斷,也就是說(shuō)CAS是一條CPU的原子指令,不會(huì)造成所謂的數(shù)據(jù)不一致的問(wèn)題,即CAS是線程安全的
在JDK中,主要體現(xiàn)在sun.misc.Unsafe類(lèi)。
當(dāng)執(zhí)行UnSafe類(lèi)中的cas相關(guān)方法時(shí), JVM會(huì)轉(zhuǎn)換成類(lèi)似匯編指令,通過(guò)它實(shí)現(xiàn)了原子操作。
來(lái)看個(gè)代碼
package com.artisan.juc;import java.util.concurrent.atomic.AtomicInteger;/*** @author 小工匠* @version 1.0* @description: TODO* @date 2021/11/6 13:11* @mark: show me the code , change the world*/ public class CASTest {public static void main(String[] args) {// 設(shè)置初始值為100AtomicInteger atomicInteger = new AtomicInteger(100);// 使用atomicInteger的compareAndSet,如果為100,則更新為123boolean b = atomicInteger.compareAndSet(100, 123);System.out.println(b + "----" + atomicInteger.get());// 使用atomicInteger的compareAndSet,如果為100,則更新為456 (上一步已經(jīng)更新成了123,所以不是100)b = atomicInteger.compareAndSet(100, 456);System.out.println(b + "----" + atomicInteger.get());} }輸出
true----123 false----123以AtomicInteger為例底層原理剖析
繼續(xù)在上個(gè)例子的基礎(chǔ)上,完善一下,方便引入知識(shí)點(diǎn),增加紅框內(nèi)如下代碼:
輸出
我們來(lái)分析下 getAndIncrement
先看看 AtomicInteger類(lèi)
看方法的注釋說(shuō)明: 以原子的方式在當(dāng)前值的基礎(chǔ)上加1 ,返回的是加1之前的值。
可以看到其實(shí)是調(diào)用了unsafe# getAndAddInt
那先看看Unsafe類(lèi) 唄
內(nèi)部方法操作可以像C的指針一樣直接操作內(nèi)存
Unsafe位于sun.misc包中,該類(lèi)的方法都是native的本地方法 ,這也意味著unsafe類(lèi)中的方法都直接調(diào)用操作系統(tǒng)底層資源執(zhí)行相應(yīng)的任務(wù)。
Unsafe類(lèi)是CAS的核心類(lèi). 我們知道Java無(wú)法直接訪問(wèn)底層操作系統(tǒng),需要通過(guò)native方法來(lái)實(shí)現(xiàn)。 Unsafe這個(gè)魔法類(lèi)可以理解為一個(gè)后門(mén),通過(guò)該類(lèi)可以直接操作特定的內(nèi)存數(shù)據(jù)。
繼續(xù)【getAndAddInt方法 】
到
到
-
var1: AtomicInteger本對(duì)象
-
var2: 該對(duì)象值得引用地址
-
var4: 需要變動(dòng)的數(shù)量
-
var5: var5 = this.getIntVolatile(var1, var2); 從主內(nèi)存中拿到的值 , 如果當(dāng)前值和期望值一樣,就執(zhí)行 var5 + var4 . (用var1和var2找到的內(nèi)存中的真實(shí)值用該對(duì)象當(dāng)前的值與var5比較)
do while 循環(huán) , 如果compareAndSwapInt返回false,那么就一直執(zhí)行 while方法,直到期望的值和真實(shí)值一樣
CAS有3個(gè)操作數(shù),內(nèi)存值V,舊的預(yù)期值,要修改的更新值。當(dāng)且僅當(dāng)預(yù)期值和內(nèi)存值相同時(shí),將內(nèi)存值修改為更新值,否則不操作 .
CAS缺點(diǎn)
CAS不加鎖,保證一致性,但是需要多次比較
-
對(duì)于多個(gè)共享變量操作時(shí),循環(huán)CAS就無(wú)法保證操作的原子性,這個(gè)時(shí)候只能用鎖來(lái)保證原子性
-
循環(huán)時(shí)間長(zhǎng),開(kāi)銷(xiāo)大(因?yàn)閳?zhí)行的是do while,如果比較不成功一直在循環(huán),最差的情況,就是某個(gè)線程一直取到的值和預(yù)期值都不一樣,這樣就會(huì)無(wú)限循環(huán))
-
只能保證一個(gè)共享變量的原子操作,當(dāng)對(duì)一個(gè)共享變量執(zhí)行操作時(shí),我們可以通過(guò)循環(huán)CAS的方式來(lái)保證原子操作
ABA 問(wèn)題
如果一個(gè)變量初次讀取的時(shí)候是 A 值,它的值被改成了 B,后來(lái)又被改回為 A,那 CAS 操作就會(huì)誤認(rèn)為它從來(lái)沒(méi)有被改變過(guò)。
總結(jié)
以上是生活随笔為你收集整理的每日一博 - CAS(Compare-And-Swap)原理剖析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 每日一博 - Semaphore使用场景
- 下一篇: 每日一博 - 如何理解跳表(SkipLi