天天看點

LongAdder源碼閱讀筆記

功能描述

LongAdder通過建立多個副本對象,解決了多線程使用CAS更新同一個對象造成的CPU阻塞,加快了對線程處理的速度。當多個線程同一時刻更新一個AtomicLong類型的變量時,隻有一個線程能夠更新成功,其他線程則更新失敗,繼續嘗試更新。

LongAdder源碼閱讀筆記

當使用LongAdder類型的變量時,由于副本數組的存在,線程不一定直接更新變量的本身而是更新副本數組,這樣多線程請求的對象變多了,進而減少了更新時間,當需要使用變量值時,傳回的值是基礎變量的值加上數組内每一個副本的值的和。

LongAdder源碼閱讀筆記

源碼解析

LongAdder繼承自Striped64并實作了Serializable接口,而在Striped64類中有一個Cell類

LongAdder源碼閱讀筆記

首先分析LongAdder類的add方法

public void add(long x) {
    Cell[] as; long b, v; int m; Cell a;
    if ((as = cells) != null || !casBase(b = base, b + x)) {
        boolean uncontended = true;
        if (as == null || (m = as.length - 1) < 0 ||
            (a = as[getProbe() & m]) == null ||
            !(uncontended = a.cas(v = a.value, v + x)))
            longAccumulate(x, null, uncontended);
    }
}
           

從上面的代碼可以看到LongAdder的實作主要依靠的是cells數組,如果cells數組為空的話,則嘗試使用cas更新基礎變量base,如果成功了,則add成功,方法結束,如果cas更新base失敗了,則證明此時有其他線程參與base變量的更新,此後的處理與cells不為空一緻(如果cells不為空,則在此次方法執行前就已經有多線程參與了更新)。

當cells數組不為空或者更新base變量失敗後