多线程中数字递增方式比较:sync atomic LongAdd
2021-02-28 本文已影响0人
Mr_Editor
三种递增方式
- 递增时加锁 sync
- 原子类AtomicXXX (CAS)
- LongAdder
多线程对一个数进行递增这个事儿,我们工作中经常会碰上,比如在秒杀时候。那么这三种方式那种效率更搞一些呢?许多测试来看AtomicXXX比不上sync,但是在我的测试上来看,起码在测试条件下AtomicXXX比sync的效率要高很多。我们来看程序,count1,count2,cunt3分别是一下不同的方式实现递增,一上来启动了1000个线程(线程比较多,少了模拟不了高并发)
/**
* @author haowq 2021/2/28 14:29
*/
public class PerformCompare {
static AtomicLong count1 = new AtomicLong(0L);
static long count2 = 0L;
static LongAdder count3 = new LongAdder();
public static void main(String[] args) throws InterruptedException {
Thread[] threads = new Thread[1000];
//方式1 sync
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(() -> {
for (int k = 0; k < 100000; k++) count1.incrementAndGet();
});
}
long start = System.currentTimeMillis();
for (Thread t : threads) t.start();
for (Thread t : threads) t.join();
long end = System.currentTimeMillis();
System.out.println("Atomic: " + count1.get() + " time: " + (end - start));
System.out.println("-----------------------------------------------------");
Object lock = new Object();
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(() -> {
for (int k = 0; k < 100000; k++) synchronized (lock){count2++;};
});
}
start = System.currentTimeMillis();
for (Thread t : threads) t.start();
for (Thread t : threads) t.join();
end = System.currentTimeMillis();
System.out.println("Sync: " + count2 + " time: " + (end - start));
System.out.println("-----------------------------------------------------");
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(() -> {
for (int k = 0; k < 100000; k++) count3.increment();
});
}
start = System.currentTimeMillis();
for (Thread t : threads) t.start();
for (Thread t : threads) t.join();
end = System.currentTimeMillis();
System.out.println("LongAddre: " + count3 + " time: " + (end - start));
System.out.println("-----------------------------------------------------");
}
}
Atomic: 100000000 time: 1615
-----------------------------------------------------
Sync: 100000000 time: 3208
-----------------------------------------------------
LongAddre: 100000000 time: 560
-----------------------------------------------------
Process finished with exit code 0
结果
LongAdder > Atomic > Sync
分析
为什么Atomic 比Sync快呢,因为sync是要加锁的,有可能它要去操作系统申请重量级锁,所以sync 效率偏低,在这种情况下效率偏低
为什么LongAdder 比Atomic 效率更高呢?
LongAdder 的内部做了一个分段锁,类似于分段锁的概念。在它内部的时候,会把一个值放到一个数组中,比如说数组长度时4,最开始时0,1000个线程,250个线程锁在第一个数组元素里,以此类推,每一个都往上递增算出来结果加到一起。