对于Synchronized、ReentrantLock、Atomic、CAS在并发下面的性能比较,在JDK1.6和JDK1.8下面测试通过。
我们考虑一个最简单的并发场景,对对象自增字段在并发下面的处理:
接口:Counter
public interface Counter {
void increment();
long getCounter();
}
执行线程:CounterThread
public class CounterThread implements Runnable{
private Counter counter;
private int num;
public CounterThread(Counter counter , int num){
this.counter = counter;
this.num = num;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<num;i++){
counter.increment();
}
}
}
不考虑线程安全的前提下,设计的普通子类:NormalCounter
/**
* @author chenmeiyang
* 普通版本
*/
public class NormalCounter implements Counter{
private long num = 0;
@Override
public void increment() {
// TODO Auto-generated method stub
num++;
}
@Override
public long getCounter() {
// TODO Auto-generated method stub
return num;
}
}
主程序入口:ConcurrencyTest
public class ConcurrencyTest {
public static void main(String[] args)throws Exception{
int threads = 1000;//线程数
int increments = 100000;
// Counter c = new ReentrantLockCounter();
Counter c = new NormalCounter();
// Counter c = new SynchronizedCounter();
// Counter c = new AtomicCounter();
ExecutorService pool = Executors.newFixedThreadPool( threads );
long start = System.currentTimeMillis();
for(int i=0;i<threads;i++){
pool.submit(new CounterThread(c , increments));
}
pool.shutdown();
pool.awaitTermination(1, TimeUnit.MINUTES);
System.out.println("=====线程池是否已经停止运行:"+pool.isTerminated());
System.out.println("===========总共耗时:"+(System.currentTimeMillis()-start));
System.out.println("======最终值为:"+c.getCounter());
}
}
执行结果:(线程不安全,数据不正确)
=====线程池是否已经停止运行:true
===========总共耗时:858
======最终值为:94046638
=====线程池是否已经停止运行:true
===========总共耗时:751
======最终值为:96394997
=====线程池是否已经停止运行:true
===========总共耗时:889
======最终值为:95764624
=====线程池是否已经停止运行:true
===========总共耗时:920
======最终值为:97167161
用jdk自带的关键字synchroized加锁处理:SynchronizedCounter
public class SynchronizedCounter implements Counter {
private long num = 0;
@Override
public synchronized void increment() {
// TODO Auto-generated method stub
num++;
}
@Override
public long getCounter() {
// TODO Auto-generated method stub
return num;
}
}
synchronized执行结果:(线程安全,保证了数据的正确性,但是耗时较长)
=====线程池是否已经停止运行:true
===========总共耗时:4625
======最终值为:100000000
=====线程池是否已经停止运行:true
===========总共耗时:4952
======最终值为:100000000
=====线程池是否已经停止运行:true
===========总共耗时:4558
======最终值为:100000000
下面,用ReentrantLock锁处理:ReentrantLockCounter
public class ReentrantLockCounter implements Counter{
private long counter = 0;
private ReentrantLock lock = new ReentrantLock();
@Override
public void increment() {
// TODO Auto-generated method stub
try{
lock.lock();
counter++;
}catch(Exception e){
e.printStackTrace();
}finally{
lock.unlock();
}
}
@Override
public long getCounter() {
// TODO Auto-generated method stub
return this.counter;
}
}
运行结果:(线程安全,数据正确,而且耗时比synchronized短)
=====线程池是否已经停止运行:true
===========总共耗时:3073
======最终值为:100000000
=====线程池是否已经停止运行:true
===========总共耗时:3058
======最终值为:100000000
=====线程池是否已经停止运行:true
===========总共耗时:3044
======最终值为:100000000
=====线程池是否已经停止运行:true
===========总共耗时:3075
======最终值为:100000000
下面,用Atomic试试:AtomicCounter
public class AtomicCounter implements Counter{
private AtomicLong num = new AtomicLong(0);
@Override
public void increment() {
// TODO Auto-generated method stub
num.incrementAndGet();
}
@Override
public long getCounter() {
// TODO Auto-generated method stub
return num.get();
}
}
运行结果,(线程安全,数据正确,耗时比ReentrantLock还短)
=====线程池是否已经停止运行:true
===========总共耗时:2636
======最终值为:100000000
=====线程池是否已经停止运行:true
===========总共耗时:2449
======最终值为:100000000
=====线程池是否已经停止运行:true
===========总共耗时:2558
======最终值为:100000000
=====线程池是否已经停止运行:true
===========总共耗时:2543
======最终值为:100000000
最后,我们再试下CAS:
public class CASCounter implements Counter{
private volatile long num = 0;
private Unsafe unsafe;
private long offset;
public CASCounter() throws Exception {
unsafe = this.getUnsafe();
offset = unsafe.objectFieldOffset(CASCounter.class.getDeclaredField("num"));
}
private Unsafe getUnsafe()throws Exception{
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
Unsafe unsafe = (Unsafe) f.get(null);
return unsafe;
}
@Override
public void increment() {
// TODO Auto-generated method stub
long before = num;
while (!unsafe.compareAndSwapLong(this, offset, before, before + 1)) {
before = num;
}
}
@Override
public long getCounter() {
// TODO Auto-generated method stub
return num;
}
}
运行结果:(线程安全,数据正确,但是耗时很长)
=====线程池是否已经停止运行:true
===========总共耗时:8505
======最终值为:100000000
=====线程池是否已经停止运行:true
===========总共耗时:9003
======最终值为:100000000