`

ReentrantLock和synchronized的性能对比

阅读更多
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytpo8

ReentrantLock和内部锁的性能对比
    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来实现同步:
package net.rubyeye.concurrency.chapter13;

public class SynchronizeBenchmark implements Counter {
    private long count = 0;

    public long getValue() {
        return count;
    }

    public synchronized void increment() {
        count++;
    }
}

采用ReentrantLock的版本,切记要在finally中释放锁,这是与synchronize使用方式最大的不同,内部锁jvm会自动帮你释放锁,而ReentrantLock需要你自己来处理。
package net.rubyeye.concurrency.chapter13;

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
        return count;
    }

    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }

}

    写一个测试程序,使用CyclicBarrier来等待所有任务线程创建完毕以及所有任务线程计算完成,清单如下:
package net.rubyeye.concurrency.chapter13;

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() {
        try {
            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();
                barrier.await();
            } 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的内部锁机制进行了调整。
分享到:
评论

相关推荐

    ReentrantLock与synchronized

    在Java多线程编程中,`ReentrantLock`和`synchronized`都是用于实现线程同步的重要工具,确保在并发环境中数据的一致性和正确性。两者虽然都能实现互斥访问,但在功能、性能以及使用场景上有所不同。下面我们将深入...

    ReentrantLock 与 synchronized 简介

    ### ReentrantLock 与 synchronized 的比较 #### 一、引言 在Java中,多线程和并发控制一直是程序员关注的重点。随着Java的发展,其语言本身及标准库提供了丰富的工具来帮助开发者处理并发问题。其中,`...

    22 到底哪把锁更适合你?—synchronized与ReentrantLock对比.pdf

    2. **性能对比**: - 在Java 5.0初期,`ReentrantLock`的性能优于`synchronized`,尤其是处理大量线程时。然而,从Java 6开始,内置锁通过优化算法提升了性能,两者在性能上的差距变得不明显。因此,性能不应成为...

    Lock、Synchoronized和ReentrantLock的使用

    Lock、Synchronized 和 ReentrantLock 的使用 Lock、Synchronized 和 ReentrantLock 是 Java 中三种常用的同步机制,每种机制都有其特点和使用场景。下面对这三种机制进行详细的分析和比较。 一、Synchronized ...

    Java synchronized使用案例

    Java中的`synchronized`关键字是多线程编程中的一个重要概念,用于控制并发访问共享资源,以保证数据的一致性和完整性。这个关键词提供了互斥锁机制,防止多个线程同时执行同一段代码,确保了线程安全。 一、`...

    Java 多线程与并发(11-26)-JUC锁- ReentrantLock详解.pdf

    **ReentrantLock与synchronized的对比** 1. **控制粒度**:synchronized是隐式的,而ReentrantLock是显式的,提供了更多的控制选项。 2. **中断支持**:ReentrantLock支持可中断的获取锁,而synchronized不支持。 3....

    [JAVA][synchronized的使用]

    - **ReentrantLock**:是Java并发包`java.util.concurrent.locks`中的可重入锁,提供了比`synchronized`更细粒度的控制,支持公平锁和非公平锁,以及可中断和可定时的获取锁。 7. **TestSynchronized 示例** 通常...

    并发编程 70 道面试题及答案.docx

    本文档总结了并发编程中的70道面试题及答案,涵盖了线程、synchronized、volatile、CAS、Lock、ReentrantLock等关键概念,旨在帮助开发者更好地理解并发编程的基本概念和机理。 线程间通信: * wait/notify机制:...

    Synchronized 终极说明教程

    六、synchronized与volatile比较 `synchronized`提供的是互斥锁,确保同一时间只有一个线程执行,而`volatile`关键字则保证了变量的可见性和有序性,但不保证原子性。对于简单读写操作,`volatile`可能更高效,但...

    Java并发系列之ReentrantLock源码分析

    ReentrantLock与synchronized的比较: * ReentrantLock提供了更加灵活的加锁机制,包括定时的锁等待、可中断的锁等待、公平锁、非阻塞结构的加锁等。 * ReentrantLock能够提供更好的性能和活跃性,特别是在高并发...

    【并发编程】简单化理解AQS和ReentrantLock.pdf

    - **性能对比**:比较`ReentrantLock`与`synchronized`关键字在特定场景下的性能差异。 ### 结论 AQS和`ReentrantLock`是Java并发编程中重要的组成部分,通过对它们的理解和掌握,可以更好地设计和实现高性能的...

    Lock接口与synchronized关键字

    #### 四、性能对比 - **synchronized**通常比Lock接口开销更小,因为它是由JVM内置支持的,经过高度优化。 - 然而,在高度竞争的并发场景下,Lock接口可能会表现出更好的性能,尤其是在利用其额外的功能特性时。 #...

    ReentrantLock实现原理详解

    了解ReentrantLock的实现原理,有助于我们在并发编程中更好地选择和使用锁,以提高程序的并发性能和可维护性。无论是synchronized还是ReentrantLock,正确理解和使用锁是并发编程的基础,也是避免线程安全问题的...

    Java多线程中ReentrantLock与Condition详解

    ReentrantLock与synchronized的比较: * ReentrantLock提供了synchronized类似的功能和内存语义,但功能性方面更全面,例如时间锁等候、可中断锁等候、锁投票等。 * ReentrantLock的性能比synchronized会好点。 * ...

    Java多线程synchronized关键字详解(六)共5

    - Java 5引入了`java.util.concurrent`包,提供了`ReentrantLock`、`Semaphore`、`CountDownLatch`等工具类,它们提供了比`synchronized`更灵活的控制和更高的性能。 10. **最佳实践** - 在不必要的情况下避免...

    HashMap与CorruntHashMap性能对比

    而`ConcurrentHashMap`的源码则更为复杂,需要处理线程安全问题,例如使用了CAS(Compare and Swap)无锁算法,以及`Synchronized`和`ReentrantLock`等同步机制。 在选择使用`HashMap`还是`ConcurrentHashMap`时,...

    juc源码视频教程最全

    3. ReentrantLock与synchronized的对比,以及如何选择合适的锁策略。 4. 并发容器的线程安全实现及性能优化技巧。 5. 原子变量的无锁编程实践和效率分析。 6. 同步工具类在多线程协调中的应用案例。 7. Future和...

    4种常用Java线程锁的特点,性能比较、使用场景.pdf

    4种常用Java线程锁的特点,性能比较、使用场景 线程(thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发...

    Java理论与实践: 一个有缺陷的微基准的剖析

    此外,JVM的即时编译器(JIT)可能在不同条件下对 `synchronized` 和 `ReentrantLock` 进行不同的优化,这会影响比较的结果。 另一个问题是,微基准通常是在孤立的环境中运行,不考虑真实世界的负载和并发条件。在 ...

Global site tag (gtag.js) - Google Analytics