天天看點

ReentrantLock和内部鎖的性能對比(update)

  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的内部鎖機制進行了調整。