1. 程式人生 > >對於Synchronized、ReentrantLock、Atomic、CAS在併發下面的效能比較測試

對於Synchronized、ReentrantLock、Atomic、CAS在併發下面的效能比較測試

對於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