Java核心锁基准测试

测试模型

基于JMH基准测试库

测试代码

package com.lsy.study.benchmark;

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.results.format.ResultFormatType;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.StampedLock;

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Thread)
@Warmup(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 10, time = 2, timeUnit = TimeUnit.SECONDS)
@Fork(1)
@Threads(2)
public class SyncTest {

    static class TaskStack {

        private volatile int task;

        TaskStack() {
            this.task = 10000000;
        }

        int getTask() {
            this.task = this.task - 1;
            return this.task;
        }
    }

    @Setup
    public void prepare() {
    }

    @Benchmark
    public void synchronizedKeyWord() {
        Object lock = new Object();
        CountDownLatch countDownLatch = new CountDownLatch(50);
        TaskStack taskStack = new TaskStack();
        for (int i = 0; i < 50; i++) {
            new Thread(() -> {
                while (true) {
                    synchronized (lock) {
                        int task = taskStack.getTask();
                        if (task <= 0) {
                            break;
                        }
                    }
                }
                countDownLatch.countDown();
            }).start();
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    @Benchmark
    public void reenterLock() {
        ReentrantLock reentrantLock = new ReentrantLock();
        CountDownLatch countDownLatch = new CountDownLatch(50);
        TaskStack taskStack = new TaskStack();
        for (int i = 0; i < 50; i++) {
            new Thread(() -> {
                while (true) {
                    reentrantLock.lock();
                    try {
                        int task = taskStack.getTask();
                        if (task <= 0) {
                            break;
                        }
                    } finally {
                        reentrantLock.unlock();
                    }
                }
                countDownLatch.countDown();
            }).start();
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Benchmark
    public void stampedLock() {
        StampedLock stampedLock = new StampedLock();
        CountDownLatch countDownLatch = new CountDownLatch(50);
        TaskStack taskStack = new TaskStack();
        for (int i = 0; i < 50; i++) {
            new Thread(() -> {
                while (true) {
                    stampedLock.writeLock();
                    try {
                        int task = taskStack.getTask();
                        if (task <= 0) {
                            break;
                        }
                    } finally {
                        stampedLock.tryUnlockWrite();
                    }
                }
                countDownLatch.countDown();
            }).start();
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    public static void main(String[] args) throws Exception {
        Options opts = new OptionsBuilder()
                .include(SyncTest.class.getSimpleName())
                .resultFormat(ResultFormatType.JSON)
                .build();
        new Runner(opts).run();
    }


}

结论图

样本一

参数:

20个线程
1000w个枪锁任务

结果

ReentrantLock: 平均用时263毫秒
StampedLock: 平均用时263毫秒
synchronized: 平均用时454毫秒
Java核心锁基准测试_第1张图片

样本二

参数:

50个线程
1000w个枪锁任务

结果

ReentrantLock: 平均用时271毫秒
StampedLock: 平均用时297毫秒
synchronized: 平均用时465毫秒

Java核心锁基准测试_第2张图片

样本三

参数:

50个线程
1w个枪锁任务

结果

ReentrantLock: 平均用时8.0毫秒
StampedLock: 平均用时8.1毫秒
synchronized: 平均用时8.9毫秒

Java核心锁基准测试_第3张图片

样本四

其实答案已经明显,用ReenterLock是为了高级特性(比如读写锁:性能肯定要更好),真要是性能区别也没多少,谁会真有几千万的并发任务在本地跑,真有synchronized关键字也简单明了,代码整洁;

你可能感兴趣的:(java,开发语言,算法)