java 原子+1 性能对比 performance


package thread;

import java.lang.reflect.Field;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.LongAdder;

import sun.misc.Unsafe;

@SuppressWarnings("restriction")
public class Sy2 {
    // 测试规模,调用一次getAndIncreaseX视作提供一次业务服务,记录提供TEST_SIZE次服务的耗时
    private static final int TEST_SIZE = 100000000;
    // 客户线程数
    private static final int THREAD_COUNT = 10;
    // 使用CountDownLatch让各线程同时开始
    private CountDownLatch cdl = new CountDownLatch(THREAD_COUNT + 1);

    private int n = 0;
    private AtomicInteger ai = new AtomicInteger(0);
    private static LongAdder longAdder = new LongAdder();
    private long startTime;

    private static volatile int value = 0;
    private static long casOffset;
    public static Unsafe unsafe;

    static {
        try {
            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafe.setAccessible(true);
            unsafe = (Unsafe) theUnsafe.get(null); // initial unsafe

            // get field offset by unsafe
            casOffset = unsafe.staticFieldOffset(Sy2.class.getDeclaredField("value"));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void init() {
        startTime = System.nanoTime();
    }

    public int cas() {
        while (true) {
            if (unsafe.compareAndSwapInt(Sy2.class, casOffset, value, value + 1))
                return value;
        }
    }

    /**
     * 使用AtomicInteger.getAndIncrement,测试结果为1.8比1.7有明显性能提升
     * 
     * @return
     */
    private final int getAndIncreaseA() {
        int result = ai.getAndIncrement();
        if (result == TEST_SIZE) {
            System.out.println(System.nanoTime() - startTime);
            System.exit(0);
        }
        return result;
    }

    /**
     * 使用synchronized来完成同步,测试结果为1.7和1.8几乎无性能差别
     * 
     * @return
     */
    private final int getAndIncreaseB() {
        int result;
        synchronized (this) {
            result = n++;
        }
        if (result == TEST_SIZE) {
            System.out.println(System.nanoTime() - startTime);
            System.exit(0);
        }
        return result;
    }

    /**
     * 使用AtomicInteger.compareAndSet在java代码层面做失败重试(与1.7的AtomicInteger.getAndIncrement的实现类似),
     * 测试结果为1.7和1.8几乎无性能差别
     * 
     * @return
     */
    private final int getAndIncreaseC() {
        int result;
        do {
            result = ai.get();
        } while (!ai.compareAndSet(result, result + 1));
        if (result == TEST_SIZE) {
            System.out.println(System.nanoTime() - startTime);
            System.exit(0);
        }
        return value;
    }

    /**
     *  自己调用 unsafe.compareAndSwapInt
     */
    private void getAndIncreaseD() {
        int result = cas();
        if (result == TEST_SIZE) {
            System.out.println(System.nanoTime() - startTime);
            System.exit(0);
        }
    }

    /**
     *  long adder 
     */
    private void getAndIncreaseE() {
        longAdder.increment();
        if(longAdder.sum() == TEST_SIZE) {
            System.out.println(System.nanoTime() - startTime);
            System.exit(0);
        }
    }


    public class MyTask implements Runnable {
        @Override
        public void run() {
            cdl.countDown();
            try {
                cdl.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            while (true)
                getAndIncreaseE();// getAndIncreaseB();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Sy2 at = new Sy2();
        for (int n = 0; n < THREAD_COUNT; n++)
            new Thread(at.new MyTask()).start();
        System.out.println("start");
        at.init();
        at.cdl.countDown();
    }

}

result (可能 根据电脑当前资源,时间有一些差异):

getAndIncreaseA --> 2146580139
getAndIncreaseB --> 4189839441
getAndIncreaseC --> 9497379502
getAndIncreaseD --> 8152335259
getAndIncreaseE --> 2326690013

java 1.8 之后的版本 AtomicInteger.getAndIncrement 在并发冲突严重时,性能有很大提升。
LongAdder 如果不频繁调用sum()函数,increment() 函数是最快的,因为内部的的加法操作时,是通过分配一个数组,hash散列 每个线程ID,最后求和各个数组的组,典型的空间换时间的操作。
当 TEST_SIZE > 10000000 时候的并发,longadder 显著高于 AtomicInteger.getAndIncrement

猜你喜欢

转载自blog.csdn.net/weixin_33853827/article/details/86810963