AtomicLong和LongAdder的区别
轉載自?https://blog.csdn.net/yao123long/article/details/63683991
前言
??最近在看到不少框架里面使用到了LongAdder這個類,而并非AtomicLong,很是困惑,于是專門看了LongAdder的源碼,總結一下這兩個的區別。
AtomicLong原理
??就像我們所知道的那樣,AtomicLong的原理是依靠底層的cas來保障原子性的更新數據,在要添加或者減少的時候,會使用死循環不斷地cas到特定的值,從而達到更新數據的目的。那么LongAdder又是使用到了什么原理?難道有比cas更加快速的方式?
LongAdder原理
??首先我們來看一下LongAdder有哪些方法?
??可以看到和AtomicLong基本類似,同樣有增加、減少等操作,那么如何實現原子的增加呢??
??我們可以看到一個Cell的類,那這個類是用來干什么的呢?
??我們可以看到Cell類的內部是一個volatile的變量,然后更改這個變量唯一的方式通過cas。我們可以猜測到LongAdder的高明之處可能在于將之前單個節點的并發分散到各個節點的,這樣從而提高在高并發時候的效率。
??下面我們來驗證我們的觀點,我們接著看上圖的add方法,如果cell數組不為空,那么就嘗試更新base元素,如果更新成功,那么就直接返回。base元素在這里起到了一個什么作用呢?可以保障的是在低并發的時候和AtomicLong一樣的直接對基礎元素進行更新。?
??而如果cell為空或者更新base失敗,我們看接下來的那個if判斷,即如果as不為空并且成功更新對應節點的數據,則返回,否則就會進入longAccumulate()方法。?
??圖有點大,無法截圖,直接貼源碼
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
??上面的代碼主要有三個分支:?
????1. 如果數組不為空?
????2. 數據為空,則初始化?
????3. 前面都更新失敗了,嘗試更新base數據?
?? cellBusy是一個標示元素,只有當修改cell數組大小或者插入元素的時候才會修改。分支二、分支三都很簡單,我們來重點分析一下分支一。?
?? 當要更新的位置沒有元素的時候,首先cas標志位,防止擴容以及插入元素,然后插入數據。如果成功直接返回,否則標示發生了沖突,然后重試。如果對應的位置有元素則更新,如果更新失敗,進行判斷是否數組的大小已經超過了cpu的核數,如果大于的話,則意味著擴容沒有意義。直接重試。否則進行擴容,擴容完成后,重新設置要更新的位置,盡可能保證下一次更新成功。?
??我們來看一下如何統計計數。?
??當計數的時候,將base和各個cell元素里面的值進行疊加,從而得到計算總數的目的。這里的問題是在計數的同時如果修改cell元素,有可能導致計數的結果不準確。
總結:
??LongAdder在AtomicLong的基礎上將單點的更新壓力分散到各個節點,在低并發的時候通過對base的直接更新可以很好的保障和AtomicLong的性能基本保持一致,而在高并發的時候通過分散提高了性能。?
??缺點是LongAdder在統計的時候如果有并發更新,可能導致統計的數據有誤差。
總結
以上是生活随笔為你收集整理的AtomicLong和LongAdder的区别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 多线程编程--异步转同步之CountDo
- 下一篇: Spring手动回滚事务