reentrantlock是jdk5引入的新的鎖機制,它與内部鎖(synchronize) 相同的并發性和記憶體語義,比如可重入加鎖語義。在中等或者更高負荷下,reentrantlock有更好的性能,并且擁有可輪詢和可定時的請求鎖等進階功能。這個程式簡單對比了reentrantlock公平鎖、reentrantlock非公平鎖以及内部鎖的性能,從結果上看,非公平的reentrantlock表現最好。内部鎖也僅僅是實作統計意義上的公平,結果也比公平的reentrantlock好上很多。這個程式僅僅是計數,啟動n個線程,對同一個counter進行遞增,顯然,這個遞增操作需要同步以保證原子性,采用不同的鎖來實作同步,然後檢視結果。
counter接口:
package net.rubyeye.concurrency.chapter13;
public interface counter {
public long getvalue();
public void increment();
}
然後,首先使用我們熟悉的synchronize來實作同步:
public class synchronizebenchmark implements counter {
private long count = 0;
public long getvalue() {
return count;
}
public synchronized void increment() {
count++;
采用reentrantlock的版本,切記要在finally中釋放鎖,這是與synchronize使用方式最大的不同,内部鎖jvm會自動幫你釋放鎖,而reentrantlock需要你自己來處理。
import java.util.concurrent.locks.lock;
import java.util.concurrent.locks.reentrantlock;
public class reentrantlockbeanchmark implements counter {
private volatile long count = 0;
private lock lock;
public reentrantlockbeanchmark() {
// 使用非公平鎖,true就是公平鎖
lock = new reentrantlock(false);
public long getvalue() {
// todo auto-generated method stub
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
寫一個測試程式,使用cyclicbarrier來等待所有任務線程建立完畢以及所有任務線程計算完成,清單如下:
import java.util.concurrent.cyclicbarrier;
public class benchmarktest {
private counter counter;
private cyclicbarrier barrier;
private int threadnum;
public benchmarktest(counter counter, int threadnum) {
this.counter = counter;
barrier = new cyclicbarrier(threadnum + 1); //關卡計數=線程數+1
this.threadnum = threadnum;
public static void main(string args[]) {
new benchmarktest(new synchronizebenchmark(), 5000).test();
//new benchmarktest(new reentrantlockbeanchmark(), 5000).test();
//new benchmarktest(new reentrantlockbeanchmark(), 5000).test();
public void test() {
for (int i = 0; i < threadnum; i++) {
new testthread(counter).start();
}
long start = system.currenttimemillis();
barrier.await(); // 等待所有任務線程建立
barrier.await(); // 等待所有任務計算完成
long end = system.currenttimemillis();
system.out.println("count value:" + counter.getvalue());
system.out.println("花費時間:" + (end - start) + "毫秒");
} catch (exception e) {
throw new runtimeexception(e);
class testthread extends thread {
private counter counter;
public testthread(final counter counter) {
this.counter = counter;
public void run() {
try {
barrier.await();
for (int i = 0; i < 100; i++)
counter.increment();
} catch (exception e) {
throw new runtimeexception(e);
分别測試一下,
将啟動的線程數限定為500,結果為:
公平reentrantlock: 210 毫秒
非公平reentrantlock : 39 毫秒
内部鎖: 39 毫秒
将啟動的線程數限定為1000,結果為:
公平reentrantlock: 640 毫秒
非公平reentrantlock : 81 毫秒
内部鎖: 60 毫秒
線程數不變,test方法中的循環增加到1000次,結果為:
公平reentrantlock: 16715 毫秒
非公平reentrantlock : 168 毫秒
内部鎖: 639 毫秒
将啟動的線程數增加到2000,結果為:
公平reentrantlock: 1100 毫秒
非公平reentrantlock: 125 毫秒
内部鎖: 130 毫秒
将啟動的線程數增加到3000,結果為:
公平reentrantlock: 2461 毫秒
非公平reentrantlock: 254 毫秒
内部鎖: 307 毫秒
啟動5000個線程,結果如下:
公平reentrantlock: 6154 毫秒
非公平reentrantlock: 623 毫秒
内部鎖: 720 毫秒
非公平reentrantlock和内部鎖的差距,在jdk6上應該縮小了,據說jdk6的内部鎖機制進行了調整。