天天看点

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的内部锁机制进行了调整。