Java LongAdder的base与cells数组的求和逻辑
Java并发包中的LongAdder类用于在高并发场景下高效地实现计数功能。其核心机制依赖于两个关键部分:base字段和cells数组。理解它们的求和逻辑对于掌握LongAdder的工作原理至关重要。
1. LongAdder的结构
LongAdder继承自Striped64类,内部维护两个主要成员:
base:一个volatile long类型的变量,用于存储低竞争情况下的计数值。cells:一个Striped64.Cell类型的数组,用于存储高竞争情况下的分片计数值。
Striped64.Cell是Striped64的内部类,包含一个volatile long value字段,用于存储每个分片的计数值。
2. base字段的作用
base字段是LongAdder的初始计数值存储位置。当并发程度较低时,所有更新操作都会直接操作base字段,避免创建cells数组带来的额外开销。
3. cells数组的作用
当并发程度较高时,LongAdder会创建cells数组,将计数值分散到不同的分片中。每个线程会根据其哈希码选择一个Cell进行更新,从而减少竞争。
4. 求和逻辑的详细步骤
当调用LongAdder的sum()方法获取当前总和时,会执行以下步骤:
4.1 读取base值
获取当前总和时,首先读取base字段的值。由于base是volatile类型,读取操作具有可见性保证。
long b = base;
4.2 检查cells数组是否存在
判断cells数组是否为空。如果数组为空,说明没有并发竞争,直接返回base的值。
if (cells == null)
return b;
4.3 遍历cells数组
如果cells数组不为空,遍历数组中的每个Cell元素,将每个Cell的value字段值累加到总和上。
long sum = b;
Striped64.Cell[] cs = cells;
for (int i = 0; i < cs.length; ++i) {
long v = cs[i].value;
sum += v;
}
4.4 返回总和
返回累加后的总和值,即base的值加上所有Cell的value值之和。
return sum;
5. 并发场景下的求和处理
在并发更新过程中,cells数组可能被动态扩容。求和操作会读取cells数组的当前状态,即使此时有其他线程在修改cells数组或其中的Cell值,volatile保证的可见性确保求和操作能够获取到相对一致的结果。
6. 示例代码
以下是一个简化的sum()方法实现,展示了上述求和逻辑:
public long sum() {
long sum = base;
Striped64.Cell[] cs = cells;
if (cs != null) {
for (int i = 0; i < cs.length; ++i) {
long v = cs[i].value;
sum += v;
}
}
return sum;
}
通过上述步骤,LongAdder能够在高并发环境下高效地计算计数值的总和,同时通过base和cells的协同工作,平衡了低竞争和高竞争场景下的性能需求。

暂无评论,快来抢沙发吧!