最近看skywalking源码 发现有一个原子类数据结构性能提升明显 10行代码 效率提升一倍 所以详细研究了一下
需求
一个原子Integer类型,范围在startValue和endValue间变化
旧的原子类
public final int getAndIncrement() {
int current;
int next;
do {
current = this.value.get();
next = current >= this.endValue ? this.startValue : current + 1;
}
while (!this.value.compareAndSet(current, next));
return current;
}
新的原子类
public final int getAndIncrement() {
int next;
do {
next = this.value.incrementAndGet();
if (next > endValue && this.value.compareAndSet(next, startValue)) {
return endValue;
}
} while (next > endValue);
return next - 1;
}
性能提升
使用Junit的Benchmark对比,我们发现
* Benchmark Mode Cnt Score Error Units
* AtomicRangeIntegerTest.testNewGetAndIncrementPerformance thrpt 5 41474285.923 ± 3595500.827 ops/s
* AtomicRangeIntegerTest.testOriGetAndIncrementPerformance thrpt 5 14199415.907 ± 1697559.657 ops/s
ops从170k增加到360k 性能翻倍
原理分析
通过源码前后变化我们可以发现 旧代码中每次都要通过compareAndSet去更新值,有很多缺点 1 冲突概率大大增加(步骤增多,冲突概率增多) 2 乐观锁自旋损耗性能(do while循环) 而新代码每次利用原子类AtomicInteger自增 减小了冲突概率 降低了锁的消耗 只在到达endValue时才会compareAndSet 并且while循环多数情况下只循环一次 所以说多看源码 看大神优化可以提高自己对并发类的认识