(九)聊一下併發中的自增原子操作的AtomicLong在JDK1.8之後是如何優化成LongAdder的,爲什麼要優化自增原子類?

(一)先聊聊AtomicLong的基本概念,然後聊一下他的缺陷問題,然後引出LongAdder的優點

(1)大家都使用過AtomicInteger、AtomicLong等這幾類原子性的工具類,具體怎麼用我就不說了,就說一下他們的大概的基本實現原理
在這裏插入圖片描述

  • 其實這些基本的原子操作的思想大體都是,
	expect 表示當前內存中你所預期望的值,update 是你想要更新的值
    public final boolean compareAndSet(long expect, long update) {
    	這個this表示了當前對象的地址,後面的valueOffset是在該對象開始的位置加上這個valueOffset的偏移量,就能拿到的是當前對象的值
        return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
    }

  • 然後這裏又會去調用unsafe對象的native方法,這個是基於C寫的代碼
把上面的compareAndSwapLong的入參和這個對應起來,然後其實就是判斷當前位置的值,是不是和你預期的expect的值相等,如果相等就把valueOffset處的值更新爲update你想要更新的結果,
如果失敗的話,就不做改變(說明這個值跟你期望的不一致,就意味着這個值被別的線程修改過了,就什麼也不操作)
public final native boolean compareAndSwapLong(Object var1, 
											long var2,  
											long var4, 
											long var6);

(2)這樣帶來的缺點就是,如果有大量的線程進行CAS的時候,那麼就會導致大量的線程都在進行CAS,但是能夠成功的又很少,那麼就會出現有大量線程進行自旋,並且對CPU造成大量的資源消耗的缺點,所以這個時候就進行了優化,那麼就出現了LongAdder

  • 但是如果要是在併發度不是很高的情況下,其實使用LongAdder和AtomicLong的差別不大
  • 儘量減少熱點衝突,不到最後萬不得已,儘量將CAS操作延遲

(二)先說一下LongAdder的整體設計思想

(1)其實整體的設計思想就是:如果在如果有很多個線程來進行CAS的時候,而在LongAdder中他其實是借鑑的了HashMap1.7的思想,他把這個資源進行分段來進行維護,他內部維護了一個Cell[]數組,每個Cell對象中就包含了資源的值,其實就是和HashMap中的那個table數組,table數組中放的都是包含key-value的一個Node對象

(2)然後在競爭激烈的時候就直接懟base值進行增加,但是如果當線程競爭足夠激烈的時候就會統計每個線程對應的Cell[這個是每個線程的hash出來的一個下標值]進行相加

value=base+∑i=0nCell[i]

在這裏插入圖片描述
(3)主要的Add方法
在這裏插入圖片描述
(4)如果
在這裏插入圖片描述
參考:https://segmentfault.com/a/1190000015865714#articleHeader4

(三)在詳細的看LongAdder的具體是如何實現的?

(四)總結一下自己的感悟和理解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章