[累加器](https://www.freesion.com/arti...)的速度快
我用AtomicLong子类模仿累加器,但是速度不行,请问我的代码比累加器差距在哪?
我先定义一个子类,用于生成超过缓存行长度的大对象。(其实我也不清楚2个这种对象是否会发生伪共享?就算不子类化,速度也还是差不多)
@sun.misc.Contended
public class MyAtomicLong extends AtomicLong {
private static final long serialVersionUID = 1L;
public MyAtomicLong(int initialValue) {
super(initialValue);
}
}
然后采用4个线程,每个线程对一个AtomicInteger对象累加
public static void main(String[] args) {
long start = System.nanoTime();
MyAtomicLong a = new MyAtomicLong(0);
MyAtomicLong b = new MyAtomicLong(0);
MyAtomicLong c = new MyAtomicLong(0);
MyAtomicLong d = new MyAtomicLong(0);
ArrayList<Thread> list = new ArrayList<Thread>();
for (int i = 0; i < 4; i++) {
int index = i;
list.add(new Thread(new Runnable() {
@Override
public void run() {
for (int j = 0; j < 50_0000; j++) {
switch (index) {
case 0:
a.incrementAndGet();
break;
case 1:
b.incrementAndGet();
break;
case 2:
c.incrementAndGet();
break;
case 3:
d.incrementAndGet();
break;
default:
break;
}
}
}
}));
}
list.forEach(Thread::start);
list.forEach(t -> {
try {
t.join();
} catch (InterruptedException e) {
System.out.println(e);
}
});
Long result = a.get() + b.get() + c.get() + d.get();
System.out.println( (System.nanoTime()-start)/1000_000 + " -- " + result);
}
为啥这代码需要100+毫秒,而累加器只要个位数?
====================更新=======================
我自己没测试累加器的结果,今天敲代码,发现花费时间和AtomicLong是差不多的,也要100毫秒上下。请大佬看看是累加器吹牛?还是我下面的代码写错了?
long start = System.nanoTime();
LongAdder adder = new LongAdder();
ArrayList<Thread> list = new ArrayList<Thread>();
for (int i = 0; i < 4; i++) {
list.add(new Thread(new Runnable() {
@Override
public void run() {
for (int j = 0; j < 50_0000; j++) {
adder.increment();
}
}
}));
}
list.forEach(Thread::start);
list.forEach(t -> {
try {
t.join();
} catch (InterruptedException e) {
System.out.println(e);
}
});
System.out.println( (System.nanoTime()-start)/1000_000 + " -- " + adder.longValue() );
LongAddr
内部持有数组。按位 hash 到数组元素,分区累加,失败则更新线程 hash 信息,减少冲突;
充分利用 CPU 核数概念,最多不超过核心数,避免浪费;
自动扩展数组大小,减少冲突,提供并发支持;
考虑过分竞争,提供喘息机会;
延迟初始化数组,避免浪费;
留有逃生门,数组太慢还可以叠加到外部基础数值。