首頁 >Java >java教程 >Java並發程式設計之LongAdder源碼分析

Java並發程式設計之LongAdder源碼分析

PHPz
PHPz轉載
2023-05-28 08:22:171404瀏覽

前言

根據原始碼分析它的基本實作流程。

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,在數組的每一個元素上都可以進行累加,最後計算結果時再就算一下basecells

數組每個元素的和就行了。而線程具體在數組的哪一位進行操作可以透過計算

hash

來決定索引位置。

原始碼簡介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語句,初始狀況下cellsnull,所以會進行casBase

操作,也就是在

base變數上進行累加,如果操作成功了表示目前沒有競爭,所以就結束了。 當並發量上來的時候,進行casBase

方法就有可能會失敗,所以這時進入第二個
    if
  • 語句判斷。

    第一次進來時Cell陣列asnull,所以就會執行longAccumulate,對Cell陣列as進行初始化並且在索引1

    位置累加
  • 1
  • ;

    之後再執行到這個if語句as就不是null

    了,而且陣列長度也大於
  • 0
  • a = as[getProbe() & m]) == null,這句話簡單的理解就是在陣列as中隨機找到索引位置,判斷該位置的值是不是null,如果是null的話就執行longAccumulate

    ,不是
  • null
  • 繼續向下判斷

    !(uncontended = a.cas(v = a.value, v x))

    這句話的意思是,在找到的這個索引位置進行累加運算,如果成功了就結束操作,如果失敗了就執行
  • longAccumulate
##########

以上是Java並發程式設計之LongAdder源碼分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除