2019-08-12-AtomicInteger實現(xiàn)原理

AtomicInteger位于java.util.concurrent.atomic包下娩贷,是對int的封裝心肪,提供原子性的訪問和更新操作棵里,其原子性操作的實現(xiàn)是基于CAS。

包下還有其他的類似原子操作類冷尉,AtomicBoolean,AtomicLong等等系枪,大家可以自行查閱雀哨,實現(xiàn)的原理都是類似的

都是提供原子性的訪問和更新操作,其原子性操作的實現(xiàn)是基于CAS私爷。

1雾棺,什么CAS算法

  • CAS(compare-and-swap)直譯即比較并交換,提供原子化的讀改寫能力衬浑,是Java 并發(fā)中所謂 lock-free 機制的基礎(chǔ)捌浩。
  • CAS的思想很簡單:三個參數(shù),一個當前內(nèi)存值V工秩、舊的預(yù)期值A(chǔ)尸饺、即將更新的值B,當且僅當預(yù)期值A(chǔ)和內(nèi)存值V相同時拓诸,將內(nèi)存值修改為B并返回true侵佃,否則什么都不做麻昼,并返回false奠支。
  • 可能會有面試官問 CAS 底層是如何實現(xiàn)的,在JAVA中,CAS通過調(diào)用C++庫實現(xiàn)抚芦,由C++庫再去調(diào)用CPU指令集倍谜。不同體系結(jié)構(gòu)中,cpu指令還存在著明顯不同叉抡。比如尔崔,x86 CPU 提供 cmpxchg 指令;而在精簡指令集的體系架構(gòu)中褥民,(如“l(fā)oad and reserve”和“store conditional”)實現(xiàn)的季春,在大多數(shù)處理器上 CAS 都是個非常輕量級的操作,這也是其優(yōu)勢所在消返。

2载弄,CAS的缺點

  • ABA問題

如果某個線程在CAS操作時發(fā)現(xiàn),內(nèi)存值和預(yù)期值都是A撵颊,就能確定期間沒有線程對值進行修改嗎宇攻?答案未必,如果期間發(fā)生了 A -> B -> A 的更新倡勇,僅僅判斷數(shù)值是 A逞刷,可能導(dǎo)致不合理的修改操作。針對這種情況,Java 提供了 AtomicStampedReference 工具類夸浅,通過為引用建立類似版本號(stamp)的方式仑最,來保證 CAS 的正確性。

  • 循環(huán)時間長開銷大

CAS中使用的失敗重試機制帆喇,隱藏著一個假設(shè)词身,即競爭情況是短暫的。大多數(shù)應(yīng)用場景中番枚,確實大部分重試只會發(fā)生一次就獲得了成功法严。但是總有意外情況,所以在有需要的時候葫笼,還是要考慮限制自旋的次數(shù)深啤,以免過度消耗 CPU。

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

3路星,AtomicInteger原理淺析

public class AtomicInteger extends Number implements java.io.Serializable {
private static final long serialVersionUID = 6214790243416807050L;

private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
private static final long VALUE;

static {
    try {
        VALUE = U.objectFieldOffset
            (AtomicInteger.class.getDeclaredField("value"));
    } catch (ReflectiveOperationException e) {
        throw new Error(e);
    }
}

private volatile int value;
}

從上面的代碼可以看出

  • 從 AtomicInteger 的內(nèi)部屬性可以看出溯街,它依賴于Unsafe 提供的一些底層能力,進行底層操作洋丐;
  • 如根據(jù)valueOffset代表的該變量值在內(nèi)存中的偏移地址呈昔,從而獲取數(shù)據(jù)的。
    變量value用volatile修飾友绝,保證了多線程之間的內(nèi)存可見性堤尾。

下面以getAndIncrement為例,說明其原子操作過程

/**
 * Atomically increments by one the current value.
 *
 * @return the previous value
 */
public final int getAndIncrement() {
    return U.getAndAddInt(this, VALUE, 1);
}

Unsafe的源碼

public final int getAndAddInt(Object var1, long var2, int var4) {
    int var5;
    do {
        var5 = this.getIntVolatile(var1, var2);
    } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

    return var5;
}
  • 假設(shè)線程1和線程2通過getIntVolatile拿到value的值都為1迁客,線程1被掛起郭宝,線程2繼續(xù)執(zhí)行
  • 線程2在compareAndSwapInt操作中由于預(yù)期值和內(nèi)存值都為1,因此成功將內(nèi)存值更新為2
  • 線程1繼續(xù)執(zhí)行掷漱,在compareAndSwapInt操作中粘室,預(yù)期值是1,而當前的內(nèi)存值為2卜范,CAS操作失敗衔统,什么都不做,返回false
  • 線程1重新通過getIntVolatile拿到最新的value為2海雪,再進行一次compareAndSwapInt操作锦爵,這次操作成功,內(nèi)存值更新為3

參考文章

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末喳魏,一起剝皮案震驚了整個濱河市棉浸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌刺彩,老刑警劉巖迷郑,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件枝恋,死亡現(xiàn)場離奇詭異,居然都是意外死亡嗡害,警方通過查閱死者的電腦和手機焚碌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來霸妹,“玉大人十电,你說我怎么就攤上這事√久” “怎么了鹃骂?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長罢绽。 經(jīng)常有香客問我畏线,道長,這世上最難降的妖魔是什么良价? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任寝殴,我火速辦了婚禮,結(jié)果婚禮上明垢,老公的妹妹穿的比我還像新娘蚣常。我一直安慰自己,他們只是感情好痊银,可當我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布抵蚊。 她就那樣靜靜地躺著,像睡著了一般曼验。 火紅的嫁衣襯著肌膚如雪泌射。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天鬓照,我揣著相機與錄音,去河邊找鬼孤紧。 笑死豺裆,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的号显。 我是一名探鬼主播臭猜,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼押蚤!你這毒婦竟也來了蔑歌?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤揽碘,失蹤者是張志新(化名)和其女友劉穎次屠,沒想到半個月后园匹,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡劫灶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年裸违,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片本昏。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡供汛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出涌穆,到底是詐尸還是另有隱情怔昨,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布宿稀,位于F島的核電站朱监,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏原叮。R本人自食惡果不足惜赫编,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望奋隶。 院中可真熱鬧擂送,春花似錦、人聲如沸唯欣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽境氢。三九已至蟀拷,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間萍聊,已是汗流浹背问芬。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留寿桨,地道東北人此衅。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像亭螟,于是被迫代替她去往敵國和親挡鞍。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,779評論 2 354

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