LongAdder快的原因?

[累加器](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() );
阅读 1.9k
1 个回答

LongAddr 内部持有数组。

按位 hash 到数组元素,分区累加,失败则更新线程 hash 信息,减少冲突;
充分利用 CPU 核数概念,最多不超过核心数,避免浪费;
自动扩展数组大小,减少冲突,提供并发支持;
考虑过分竞争,提供喘息机会;
延迟初始化数组,避免浪费;
留有逃生门,数组太慢还可以叠加到外部基础数值。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题