AtomicInteger源碼解析

??我們?cè)趯?shí)現(xiàn)一個(gè)計(jì)數(shù)器的時(shí)候,很多情況下為了考慮線程安全郁惜,需要去加鎖,防止計(jì)數(shù)器錯(cuò)亂甲锡,因?yàn)閷?duì)于大多數(shù)count++來(lái)說(shuō)兆蕉,是兩步操作。兩個(gè)步驟的操作缤沦,多線程必然會(huì)產(chǎn)生錯(cuò)亂的現(xiàn)象虎韵。而atomicInteger這些concurrent包中的計(jì)數(shù)器卻不會(huì)。下面我們來(lái)解析下源碼疚俱。以AtomicInteger為例

??首先劝术,看AtomicInteger類,有如下屬性:

private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
private volatile int value;

??這里說(shuō)明下呆奕,由此看出這個(gè)類的底層是通過(guò)Unsafe來(lái)實(shí)現(xiàn)的。也就是說(shuō)Unsafe是核心衬吆。有的人會(huì)問(wèn)梁钾,這里為什么可以通過(guò)Unsafe.getUnsafe來(lái)獲取Unsafe的實(shí)例,因?yàn)檫@個(gè)類在rt.jar 包中逊抡。系統(tǒng)的classloader加載姆泻。所以可以獲取到零酪。如果通過(guò)ApplicationClassloader加載,請(qǐng)參見(jiàn)下Unsafe源碼拇勃,明顯是會(huì)拋異常的四苇。

??接下來(lái)看看valueOffset和value的作用:

static {
        try {
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }

??初始化valueOffset,這里的得到的是內(nèi)存的偏移量方咆。根據(jù)offset可以定位jvm中分配的內(nèi)存地址月腋。這里猜測(cè)就是定一個(gè)變量value,然后初始化把他的內(nèi)存地址放入valueOffset變量里瓣赂。
??這里還有一點(diǎn)比較重要榆骚,我們看下value的定義是volatile。volatile的意義就是copy出來(lái)的副本值始終和主內(nèi)存中的值保持同步煌集。即你永遠(yuǎn)讀取的都是主內(nèi)存中最新的值妓肢。這樣子就保證了讀的一致性。也就是不管多少個(gè)線程苫纤,你讀取的value永遠(yuǎn)是一致的碉钠。

??通過(guò)以上解釋,基本可以概括出來(lái)卷拘,通過(guò)value,valueOffset喊废,unsafe這三個(gè)東西,實(shí)現(xiàn)了AtomicInteger的功能恭金。

??構(gòu)造函數(shù)比較簡(jiǎn)單操禀,無(wú)參和有參。

/**
     * Creates a new AtomicInteger with the given initial value.
     *
     * @param initialValue the initial value
     */
    public AtomicInteger(int initialValue) {
        value = initialValue;
    }

    /**
     * Creates a new AtomicInteger with initial value {@code 0}.
     */
    public AtomicInteger() {
    }

??這個(gè)相信大家在用AtomicInteger的時(shí)候横腿,用過(guò)了構(gòu)造函數(shù)了颓屑。有參的就是初始化下value的值,從初始化的值開(kāi)始計(jì)數(shù)耿焊。

??下面看下實(shí)際用的比較多的方法揪惦,以getAndIncrement舉例:

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

??這個(gè)就很好理解了,如果看了我之前寫的unsafe的那篇文章就清楚了罗侯,這段代碼的意思就是這個(gè)AtomicInteger對(duì)象的valueOffset內(nèi)存偏移對(duì)應(yīng)的值+1器腋。那么對(duì)于unsafe.getAndAddInt做了些什么。這里要講到CAS的概念了(compareAndSwap)钩杰。我們看下這段內(nèi)在的邏輯:

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;
    }

??很顯然纫塌,一個(gè)cas的做法〗才看完這段代碼措左,就知道為什么AtomicInteger效率高了,因?yàn)椴捎昧藰?lè)觀鎖的概念避除。首先獲取了對(duì)象this對(duì)應(yīng)的offset內(nèi)存偏移的值怎披。也就是當(dāng)前值:var5胸嘁。接下來(lái)在while里進(jìn)行判斷,如果該offset內(nèi)存偏移對(duì)應(yīng)的值是var5凉逛,即沒(méi)有被更改過(guò)性宏,那么就更新成var5+var4。這個(gè)就是明顯的樂(lè)觀鎖的概念状飞。如果沒(méi)更新成功毫胜,那么就直接返回啦。

??至此昔瞧,AtomicInteger核心的思想解釋完畢指蚁。大家可以試試自己去實(shí)現(xiàn)個(gè)AtomicInteger的類。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末自晰,一起剝皮案震驚了整個(gè)濱河市凝化,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌酬荞,老刑警劉巖搓劫,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異混巧,居然都是意外死亡枪向,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門咧党,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)秘蛔,“玉大人,你說(shuō)我怎么就攤上這事傍衡∩钤保” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵蛙埂,是天一觀的道長(zhǎng)倦畅。 經(jīng)常有香客問(wèn)我,道長(zhǎng)绣的,這世上最難降的妖魔是什么叠赐? 我笑而不...
    開(kāi)封第一講書人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮屡江,結(jié)果婚禮上芭概,老公的妹妹穿的比我還像新娘。我一直安慰自己惩嘉,他們只是感情好谈山,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著宏怔,像睡著了一般奏路。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上臊诊,一...
    開(kāi)封第一講書人閱讀 51,573評(píng)論 1 305
  • 那天鸽粉,我揣著相機(jī)與錄音,去河邊找鬼抓艳。 笑死触机,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的玷或。 我是一名探鬼主播儡首,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼偏友!你這毒婦竟也來(lái)了蔬胯?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤位他,失蹤者是張志新(化名)和其女友劉穎氛濒,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鹅髓,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡舞竿,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了窿冯。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片骗奖。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖醒串,靈堂內(nèi)的尸體忽然破棺而出执桌,到底是詐尸還是另有隱情,我是刑警寧澤厦凤,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布鼻吮,位于F島的核電站,受9級(jí)特大地震影響较鼓,放射性物質(zhì)發(fā)生泄漏椎木。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一博烂、第九天 我趴在偏房一處隱蔽的房頂上張望香椎。 院中可真熱鬧,春花似錦禽篱、人聲如沸畜伐。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)溉瓶。三九已至伤疙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間慎框,已是汗流浹背良狈。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留笨枯,地道東北人薪丁。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像馅精,于是被迫代替她去往敵國(guó)和親严嗜。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

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