您的位置:首页 > 其它

对于Synchronized、ReentrantLock、Atomic、CAS在并发下面的性能比较测试

2015-12-01 15:20 567 查看
对于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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: