使用微基准测试框架JMH对ReentrantLock的公平与非公平锁进行性能测试


前言

最近在阅读ReentrantLock源码的时候, 发现了Lock有公平和不公平两种锁, 查阅相关资料与博客后得知公平锁和非公平锁的性能是不一样的, 非公平锁的性能会优于公平锁.
因为FairLock在获取锁时, 永远是等待时间最长的线程获取到锁, 这样当线程释放锁以后, 如果还想继续再获取锁, 就必须去Sync队列尾部进行排队, 这样就会发生频繁的线程切换, 所以非公平锁的吞吐量就要强于公平锁

Benchmark

是openjdk提供一种基准测试的框架, 支持多种粒度的性能测试. 官方文档: https://github.com/openjdk/jmh

maven依赖

<!-- JMH-->
<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-core</artifactId>
    <version>${jmh.version}</version>
</dependency>
<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-generator-annprocess</artifactId>
    <version>${jmh.version}</version>
    <scope>provided</scope>
</dependency>

性能测试代码

利用CountDownLatch配合JMH, 测试极端条件下(获取锁之后立马释放锁, 不断循环), 不同的线程数量循环10000次加锁解锁的平均时间

代码地址

https://github.com/plum-wine/code-commons/blob/master/api/src/main/java/com/github/thread/BenchmarkFairAndNonFair.java

@Fork(1)
@Threads(1)
@Warmup(iterations = 1)
@State(Scope.Benchmark)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS)
public class BenchmarkFairAndNonFair {

    @Param({"10", "50", "100", "300", "500"})
    private int threadNum;

    private static final int FOREACH_COUNT = 10000;

    @Benchmark
    public void testFairLock() throws InterruptedException {
        final Lock fairLock = new ReentrantLock(true);
        final CountDownLatch countDownLatch = new CountDownLatch(threadNum);
        List<Thread> threads = new ArrayList<>();
        for (int i = 0; i < threadNum; i++) {
            threads.add(new Thread(() -> {
                for (int j = 0; j < FOREACH_COUNT; j++) {
                    fairLock.lock();
                    fairLock.unlock();
                }
                countDownLatch.countDown();
            }));
        }
        threads.forEach(thread -> thread.start());
        // main wait all thread
        countDownLatch.await();
    }

    @Benchmark
    public void testNonFairLock() throws InterruptedException {
        final Lock nonFairLock = new ReentrantLock(false);
        final CountDownLatch countDownLatch = new CountDownLatch(threadNum);
        List<Thread> threads = new ArrayList<>();
        for (int i = 0; i < threadNum; i++) {
            threads.add(new Thread(() -> {
                for (int j = 0; j < FOREACH_COUNT; j++) {
                    nonFairLock.lock();
                    nonFairLock.unlock();
                }
                countDownLatch.countDown();
            }));
        }
        threads.forEach(thread -> thread.start());
        // main wait all thread
        countDownLatch.await();
    }

    public static void main(String[] args) throws RunnerException {
        Options options = new OptionsBuilder()
                .include(BenchmarkFairAndNonFair.class.getSimpleName())
                .build();
        new Runner(options).run();
    }

}

性能测试结果

# Run complete. Total time: 00:08:23

Benchmark                                (threadNum)  Mode  Cnt      Score      Error  Units
BenchmarkFairAndNonFair.testFairLock              10  avgt    5    335.780 ±   13.599  ms/op
BenchmarkFairAndNonFair.testFairLock              50  avgt    5   1856.063 ±  127.977  ms/op
BenchmarkFairAndNonFair.testFairLock             100  avgt    5   3917.435 ±  673.222  ms/op
BenchmarkFairAndNonFair.testFairLock             300  avgt    5  14387.132 ± 3668.159  ms/op
BenchmarkFairAndNonFair.testFairLock             500  avgt    5  29424.262 ± 2485.551  ms/op
BenchmarkFairAndNonFair.testNonFairLock           10  avgt    5      2.383 ±    0.094  ms/op
BenchmarkFairAndNonFair.testNonFairLock           50  avgt    5     11.402 ±    0.820  ms/op
BenchmarkFairAndNonFair.testNonFairLock          100  avgt    5     23.525 ±    1.628  ms/op
BenchmarkFairAndNonFair.testNonFairLock          300  avgt    5     70.299 ±    0.746  ms/op
BenchmarkFairAndNonFair.testNonFairLock          500  avgt    5    121.046 ±    2.014  ms/op

结论

从测试结果可以可看出, 非公平锁的性能确实比公平锁要好, 而且线程数量越多, 差别越是明显

posted @ 2020-12-12 20:04  梅子酒zZ  阅读(89)  评论(0编辑  收藏  举报