AtomicInteger 源碼分析閱讀

閱讀java源碼可能是每一個java程序員的必修課,只有知其所以然,才能更好的使用java,寫出更優(yōu)美的程序,閱讀java源碼也為我們后面閱讀java框架的源碼打下了基礎(chǔ)。閱讀源代碼其實就像再看一篇長篇推理小說一樣,不能急于求成,需要慢慢品味才行。這一系列的文章,記錄了我閱讀源碼的收獲與思路,讀者也可以借鑒一下,也僅僅是借鑒,問渠那得清如許,絕知此事要躬行!要想真正的成為大神,還是需要自己親身去閱讀源碼而不是看幾篇分析源碼的博客就可以的。

正文

最近在看JAVA1.8線程池源碼的時候,發(fā)現(xiàn)對于AtomicInteger類的使用不太熟悉,所以就專門研究了一下,有一些收獲。AtomicInteger是juc(java.util.concurrent)包下提供的一個可以原子性操作Integer對象的類。通過它,我們可以很方便的對Integer進(jìn)行線程安全的加、減、改值等操作。其原理是使用的CAS無鎖算法。

 private static final long serialVersionUID = 6214790243416807050L;

    // setup to use Unsafe.compareAndSwapInt for updates
    //JAVA實現(xiàn)CAS算法的類,整個類有關(guān)線程安全的操作,都是借助它來實現(xiàn)。
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    //變量value的內(nèi)存首地址的偏移量。
    private static final long valueOffset;
    //靜態(tài)代碼塊,在類加載時運行
    static {
        try {
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }
    //存放int值
    private volatile int value;

1.unsafe 其實就是負(fù)責(zé)與CAS相關(guān)的操作實現(xiàn),這里需要提一下的是Unsafe是不符合JAVA標(biāo)準(zhǔn)的,官方不推薦大家在編寫自己的中使用它,因為它引入了和C++中指針相似的東西,但可以借用java.util.concurrent.atomic包下的類來使用。
2.valueOffset的值是變量value的內(nèi)存首地址的偏移量。,它在AtomicInteger被加載時就被賦值了。
3.value其實就是存放實際值的變量,它被volatile 關(guān)鍵字修飾,說明對于其他線程是可見的。

可能大家還是不大能夠了解valueOffset到底是個什么東西,有什么用,當(dāng)時我也在這里卡了很久,接下來我來講一下自己的分析過程。首先從字面意思來講,應(yīng)該是和value有關(guān)的一個變量。再看它是由objectFieldOffset()這個方法的返回值進(jìn)行賦值的。我們查看一下objectFieldOffset()的聲明定義:
objectFieldOffset

發(fā)現(xiàn)并沒有任何描述,但是通過百度發(fā)現(xiàn)說是value在內(nèi)存中首地址。出于嚴(yán)禁的角度,我就寫了一個測試來看看:
public class Main {

    public static void main(String[] args) {
        AtomicInteger a=new AtomicInteger(1);
        AtomicInteger b=new AtomicInteger(1);
        int c=a.addAndGet(5);
        b.addAndGet(4);
        System.out.println(a.get());
        System.out.println(c);

    }
}

addAndGet()方法的定義與聲明


addGet()

這個測試中,我實例化了兩個AtomicInteger 對象:a和b,同時在調(diào)用的方法addAndGet()中打了斷點。
最后debug發(fā)現(xiàn),兩個變量的valueOffset值都為12。說明valueOffset就是value內(nèi)存首地址的偏移量。到這里或許大家還想問,這個偏移應(yīng)該是針對于什么的偏移呢?你偏移量總得有個參照位置吧。這里就要回到我們valueOffset的定義與賦值了。

private static final long valueOffset;
    //靜態(tài)代碼塊,在類加載時運行
    static {
        try {
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }

我們可以看到,valueOffset 是一個靜態(tài)常量,并且在類加載時就被賦值了。那么這個類在編譯后的字節(jié)碼是一定的,但是存放對象的首地址是隨機(jī)的,所以這里的偏移應(yīng)該是相對于對象實例的首地址。如果大家看不明白,請看下面這幅圖,這幅圖簡介明了的描述了valueOffset 的含義。


valueOffset 的含義

再聯(lián)系到AtomicInteger在調(diào)用unsafe接口時,都將this和valueOffset 作為傳入?yún)?shù)(如下圖),我們可以了解到unsafe實現(xiàn)的CAS算法是依賴底層實現(xiàn)的(因為方法聲明有native關(guān)鍵字),我們?yōu)槠涮峁┚唧w的內(nèi)存地址,即this+valueOffset ,就可以讓其找到要進(jìn)行原子性操作的變量value,并進(jìn)行修改。


compareAndSet

unsafe中的一個方法聲明
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 在對J.U.C包的源碼分析之前,首先介紹下一個比較重要的概念-CAS(Compare-and-Swap)。在J.U...
    泰迪的bagwell閱讀 8,139評論 0 20
  • Java8張圖 11、字符串不變性 12、equals()方法、hashCode()方法的區(qū)別 13、...
    Miley_MOJIE閱讀 3,899評論 0 11
  • 獨自去一個陌生的城市,沒出發(fā)之前,和任何人說自己一個人去,你好厲害,注意安全,找同伴......如果第一次獨自出去...
    噗梅閱讀 208評論 0 0
  • 今日三朵玫瑰 1.早起 2.觀看穿刺視頻 3.準(zhǔn)備明天考試 【幸福實修99天目標(biāo)】 1.臣服父母,每天做打卡。 2...
    葉青丁當(dāng)媽閱讀 413評論 1 1
  • 那是個夏末秋初的中午,與朋友在路旁等車。 或許是“夏”感覺到季節(jié)即將終結(jié),居然越發(fā)燥熱,或許是“夏”想在最后關(guān)頭發(fā)...
    孤獨一刀閱讀 382評論 0 5

友情鏈接更多精彩內(nèi)容