根據原始碼分析它的基本實作流程。
This class is usually preferable to AtomicLong when multiple threads update a common sum that is used for purposes such as collecting statistics, not for fine-graine purposion the class control. similar characteristics. But under high contention, expected throughput of this class is significantly higher, at the expense of higher space consumption.
#這段話是LongAdder
##li字源一部分,翻譯過來意思大概是
AtomicLong。 在低更新爭用下,這兩個類別具有相似的特徵。 但在高爭用的情況下,這一類的預期吞吐量明顯較高,但代價是空間消耗較高。
LongAdder在並發度高的情況下效率更高,但是代價是以空間換時間。
通俗地解釋一下
LongAdder的原理:當並發少的時候,累加操作只在一個變數
base上執行就夠用了,所以和
AtomicLong類似;但是當並發量上來的時候,如果還是在變數
base#上進行操作就會有很多線程阻塞,所以就創建一個數組
cells,在數組的每一個元素上都可以進行累加,最後計算結果時再就算一下
base和
cells
原始碼簡介
LongAdder
從父類別
Striped64繼承過來的屬性,這裡的
Cell
value屬性來儲存累加的值。
// CPU核心数 static final int NCPU = Runtime.getRuntime().availableProcessors(); // 并发高时进行累加的Cell数组 transient volatile Cell[] cells; // 多个线程没有竞争时在base上进行累加 transient volatile long base; // Cell数组是否正在创建或扩容 transient volatile int cellsBusy;
累積操作方法
increment()實際呼叫的是
add(1L),所以我們直接來看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); } }
首先來看第一個
if語句,初始狀況下
cells是
null,所以會進行
casBase操作,也就是在base變數上進行累加,如果操作成功了表示目前沒有競爭,所以就結束了。
當並發量上來的時候,進行
casBase
第一次進來時
Cell陣列
as是
null,所以就會執行
longAccumulate,對
Cell陣列
as進行初始化並且在索引
1
之後再執行到這個
if語句
as就不是
null
a = as[getProbe() & m]) == null
,這句話簡單的理解就是在陣列
as中隨機找到索引位置,判斷該位置的值是不是
null,如果是
null的話就執行
longAccumulate
!(uncontended = a.cas(v = a.value, v x))
以上是Java並發程式設計之LongAdder源碼分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!