You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中LongAdder的使用要点及相关概念疑问解析

Answers to Your LongAdder Questions

Hey there! Let's break down the two questions you have about LongAdder from Cay S. Horstmann's Core Java I (page 580):

First, let's recap the key quote from the book for context:

如果预计会出现高竞争[*1],你应该直接使用LongAdder而非AtomicLong。二者的方法名称略有不同,调用increment方法可实现计数器自增,调用add方法可添加一个数值,调用sum方法可获取总计值。
注意:当然,increment方法不会返回旧值[*2]。如果返回旧值,会抵消将总和拆分为多个求和项所带来的效率提升。

And here's the example code provided:

var adder = new LongAdder();
for (...) pool.submit(() -> {
    while (...) {
        ...
        if (...) adder.increment();
    }
});
...
long total = adder.sum();

1. What does "high contention" [*1] refer to?

Your guess about machine load is close but not quite right. Here, "contention" specifically means competition among threads for access to a shared resource—in this case, the counter itself.

When using AtomicLong, all threads try to update a single, shared value via CAS (Compare-And-Swap) operations. If multiple threads hit this value at the same time, many will fail the CAS check and have to retry repeatedly. This constant retrying is what "high contention" looks like, and it slows things down.

LongAdder fixes this by splitting the single global counter into multiple independent "cells". Threads will typically update their own dedicated cell instead of fighting over one shared value, drastically reducing contention. So "high contention" here describes scenarios where lots of threads are trying to update the counter simultaneously.

2. What do "old value" / "new value" mean, and why returning the old value kills efficiency?

Let's start with the terms:

  • Old value: The counter's value before the increment runs. For example, if the counter was at 10, the old value is 10 when you call increment().
  • New value: The counter's value after incrementing—so 11 in that example.

With AtomicLong, you can use getAndIncrement() which returns the old value. But LongAdder's increment() has no return value, and here's why:

LongAdder's speed comes from splitting the total across multiple cells. To return the old value, it would first need to calculate the current global total by summing all cells. But this sum isn't atomic—between the time it finishes summing and actually performs the increment, other threads could have updated cells, making the "old value" inaccurate. Worse, summing all cells every time you increment would add significant overhead, completely wiping out the performance gain from splitting the counter into cells.

Instead, LongAdder prioritizes speed: you call increment() to update quickly, and sum() separately when you need the total (note that sum() gives an approximate value since cells might be updated while it's running, which is acceptable for most counter use cases).


内容的提问来源于stack exchange,提问作者tahasozgen2

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 09:02:32