LongAdder原始碼閱讀筆記
阿新 • • 發佈:2021-06-12
功能描述
LongAdder通過建立多個副本物件,解決了多執行緒使用CAS更新同一個物件造成的CPU阻塞,加快了對執行緒處理的速度。當多個執行緒同一時刻更新一個AtomicLong型別的變數時,只有一個執行緒能夠更新成功,其他執行緒則更新失敗,繼續嘗試更新。
當使用LongAdder型別的變數時,由於副本陣列的存在,執行緒不一定直接更新變數的本身而是更新副本陣列,這樣多執行緒請求的物件變多了,從而減少了更新時間,當需要使用變數值時,返回的值是基礎變數的值加上陣列內每一個副本的值的和。
原始碼解析
LongAdder繼承自Striped64並實現了Serializable介面,而在Striped64類中有一個Cell類
首先分析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變數失敗後