并發(fā)性能優(yōu)化之使用LongAdder替換AtomicLong

LongAdder

本文轉(zhuǎn)載自占小狼

如果讓你實(shí)現(xiàn)一個(gè)計(jì)數(shù)器,有點(diǎn)經(jīng)驗(yàn)的同學(xué)可以很快的想到使用AtomicInteger或者AtomicLong進(jìn)行簡單的封裝。
因?yàn)橛?jì)數(shù)器操作涉及到內(nèi)存的可見性和線程之間的競(jìng)爭,而Atomic*的實(shí)現(xiàn)完美的屏蔽了這些技術(shù)細(xì)節(jié)肤频,我們只需要執(zhí)行相應(yīng)的方法,就能實(shí)現(xiàn)對(duì)應(yīng)的業(yè)務(wù)需求。
Atomic
雖然好用梗顺,不過這些的操作在并發(fā)量很大的情況下,性能問題也會(huì)被相應(yīng)的放大车摄。我們可以先看下其中getAndIncrement的實(shí)現(xiàn)代碼

public final long getAndIncrement() {
    return unsafe.getAndAddLong(this, valueOffset, 1L);
}

// unsafe類中的實(shí)現(xiàn)
public final long getAndAddLong(Object var1, long var2, long var4) {
    long var6;
    do {
        var6 = this.getLongVolatile(var1, var2);
    } while(!this.compareAndSwapLong(var1, var2, var6, var6 + var4));

    return var6;
}

很顯然寺谤,在getAndAddLong實(shí)現(xiàn)中仑鸥,為了實(shí)現(xiàn)正確的累加操作,如果并發(fā)量很大的話变屁,cpu會(huì)花費(fèi)大量的時(shí)間在試錯(cuò)上面眼俊,相當(dāng)于一個(gè)spin的操作。如果并發(fā)量小的情況粟关,這些消耗可以忽略不計(jì)泵琳。
既然已經(jīng)意識(shí)到Atomic***有這樣的業(yè)務(wù)缺陷,Doug Lea大神又給我們提供了LongAdder誊役,內(nèi)部的實(shí)現(xiàn)有點(diǎn)類似ConcurrentHashMap的分段鎖获列,最好的情況下,每個(gè)線程都有獨(dú)立的計(jì)數(shù)器蛔垢,這樣可以大量減少并發(fā)操作击孩。

下面通過JMH比較一下AtomicLong 和 LongAdder的性能。

@OutputTimeUnit(TimeUnit.MICROSECONDS)
@BenchmarkMode(Mode.Throughput)
public class Main {

    private static AtomicLong count = new AtomicLong();
    private static LongAdder longAdder = new LongAdder();
    public static void main(String[] args) throws Exception {
        Options options = new OptionsBuilder().include(Main.class.getName()).forks(1).build();
        new Runner(options).run();
    }

    @Benchmark
    @Threads(10)
    public void run0(){
        count.getAndIncrement();
    }

    @Benchmark
    @Threads(10)
    public void run1(){
        longAdder.increment();
    }
}

1鹏漆、設(shè)置BenchmarkMode為Mode.Throughput巩梢,測(cè)試吞吐量
2、設(shè)置BenchmarkMode為Mode.AverageTime艺玲,測(cè)試平均耗時(shí)
線程數(shù)為1

1括蝠、吞吐量

Benchmark   Mode  Cnt    Score   Error   Units
Main.run0  thrpt    5  154.525 ± 9.767  ops/us
Main.run1  thrpt    5   89.599 ± 7.951  ops/us

2、平均耗時(shí)

Benchmark  Mode  Cnt  Score    Error  Units
Main.run0  avgt    5  0.007 ±  0.001  us/op
Main.run1  avgt    5  0.011 ±  0.001  us/op

單線程情況:
1饭聚、AtomicLong的吞吐量和平均耗時(shí)都占優(yōu)勢(shì)
線程數(shù)為10

1忌警、吞吐量

Benchmark   Mode  Cnt    Score     Error   Units
Main.run0  thrpt    5   37.780 ±   1.891  ops/us
Main.run1  thrpt    5  464.927 ± 143.207  ops/us

2、平均耗時(shí)

Benchmark  Mode  Cnt  Score   Error  Units
Main.run0  avgt    5  0.290 ± 0.038  us/op
Main.run1  avgt    5  0.021 ± 0.001  us/op

并發(fā)線程為10個(gè)時(shí):

LongAdder的吞吐量比較大秒梳,是AtomicLong的10倍多法绵。
LongAdder的平均耗時(shí)是AtomicLong的十分之一。
線程數(shù)為30

1酪碘、吞吐量

Benchmark   Mode  Cnt    Score    Error   Units
Main.run0  thrpt    5   36.215 ±  2.341  ops/us
Main.run1  thrpt    5  486.630 ± 26.894  ops/us

2朋譬、平均耗時(shí)

Main.run0  avgt    5  0.792 ± 0.021  us/op
Main.run1  avgt    5  0.063 ± 0.002  us/op

線程數(shù)為30個(gè)時(shí):

  • LongAdder的吞吐量比較大,也是AtomicLong的10倍多兴垦。
  • LongAdder的平均耗時(shí)也是AtomicLong的十分之一徙赢。

總結(jié)

一些高并發(fā)的場(chǎng)景,比如限流計(jì)數(shù)器探越,建議使用LongAdder替換AtomicLong狡赐,性能可以提升不少。

關(guān)注我扶关,這里只有干貨阴汇!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市节槐,隨后出現(xiàn)的幾起案子搀庶,更是在濱河造成了極大的恐慌拐纱,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哥倔,死亡現(xiàn)場(chǎng)離奇詭異秸架,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)咆蒿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門东抹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人沃测,你說我怎么就攤上這事缭黔。” “怎么了蒂破?”我有些...
    開封第一講書人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵馏谨,是天一觀的道長。 經(jīng)常有香客問我附迷,道長惧互,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任喇伯,我火速辦了婚禮喊儡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘稻据。我一直安慰自己艾猜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開白布攀甚。 她就那樣靜靜地躺著箩朴,像睡著了一般。 火紅的嫁衣襯著肌膚如雪秋度。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,692評(píng)論 1 305
  • 那天钱床,我揣著相機(jī)與錄音荚斯,去河邊找鬼。 笑死查牌,一個(gè)胖子當(dāng)著我的面吹牛事期,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播纸颜,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼兽泣,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了胁孙?” 一聲冷哼從身側(cè)響起唠倦,我...
    開封第一講書人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤称鳞,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后稠鼻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體冈止,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年候齿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了熙暴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡慌盯,死狀恐怖周霉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情亚皂,我是刑警寧澤诗眨,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站孕讳,受9級(jí)特大地震影響匠楚,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜厂财,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一芋簿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧璃饱,春花似錦与斤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至谒撼,卻和暖如春食寡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背廓潜。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來泰國打工抵皱, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人辩蛋。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓呻畸,卻偏偏與公主長得像,于是被迫代替她去往敵國和親悼院。 傳聞我的和親對(duì)象是個(gè)殘疾皇子伤为,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容