日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java 并发包之 LongAdder 源码分析

發布時間:2023/12/18 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 并发包之 LongAdder 源码分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。

LongAdder是java8中新增的原子類,在多線程環境中,它比AtomicLong性能要高出不少,特別是寫多的場景。

它是怎么實現的呢?讓我們一起來學習吧。

原理

LongAdder的原理是,在最初無競爭時,只更新base的值,當有多線程競爭時通過分段的思想,讓不同的線程更新不同的段,最后把這些段相加就得到了完整的LongAdder存儲的值。

源碼分析

LongAdder繼承自Striped64抽象類,Striped64中定義了Cell內部類和各重要屬性。

主要內部類

Cell類使用@sun.misc.Contended注解,說明是要避免偽共享的。

使用Unsafe的CAS更新value的值,其中value的值使用volatile修飾,保證可見性。

關于Unsafe的介紹請查看【死磕 java魔法類之Unsafe解析】。

關于偽共享的介紹請查看【雜談 什么是偽共享(false sharing)?】。

主要屬性

最初無競爭或有其它線程在創建cells數組時使用base更新值,有過競爭時使用cells更新值。

最初無競爭是指一開始沒有線程之間的競爭,但也有可能是多線程在操作,只是這些線程沒有同時去更新base的值。

有過競爭是指只要出現過競爭不管后面有沒有競爭都使用cells更新值,規則是不同的線程hash到不同的cell上去更新,減少競爭。

add(x)方法

add(x)方法是LongAdder的主要方法,使用它可以使LongAdder中存儲的值增加x,x可為正可為負。


(1)最初無競爭時只更新base;

(2)直到更新base失敗時,創建cells數組;

(3)當多個線程競爭同一個Cell比較激烈時,可能要擴容;

sum()方法

sum()方法

可以看到sum()方法是把base和所有段的值相加得到,那么,這里有一個問題,如果前面已經累加到sum上的Cell的value有修改,不是就沒法計算到了么?

答案確實如此,所以LongAdder可以說不是強一致性的,它是最終一致性的。

LongAdder VS AtomicLong

當只有一個線程的時候,AtomicLong反而性能更高,隨著線程越來越多,AtomicLong的性能急劇下降,而LongAdder的性能影響很小。

總結

(1)LongAdder通過base和cells數組來存儲值;

(2)不同的線程會hash到不同的cell上去更新,減少了競爭;

(3)LongAdder的性能非常高,最終會達到一種無競爭的狀態;

彩蛋

在longAccumulate()方法中有個條件是?n>=NCPU就不會走到擴容邏輯了,而n是2的倍數,那是不是代表cells數組最大只能達到大于等于NCPU的最小2次方?

答案是明確的。因為同一個CPU核心同時只會運行一個線程,而更新失敗了說明有兩個不同的核心更新了同一個Cell,這時會重新設置更新失敗的那個線程的probe值,這樣下一次它所在的Cell很大概率會發生改變,如果運行的時間足夠長,最終會出現同一個核心的所有線程都會hash到同一個Cell(大概率,但不一定全在一個Cell上)上去更新,所以,這里cells數組中長度并不需要太長,達到CPU核心數足夠了。

比如,筆者的電腦是8核的,所以這里cells的數組最大只會到8,達到8就不會擴容了。

總結

以上是生活随笔為你收集整理的java 并发包之 LongAdder 源码分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。