使用微基準測試框架JMH對ReentrantLock的公平與非公平鎖進行效能測試
阿新 • • 發佈:2020-12-12
目錄
前言
最近在閱讀ReentrantLock原始碼的時候, 發現了Lock有公平和不公平兩種鎖, 查閱相關資料與部落格後得知公平鎖和非公平鎖的效能是不一樣的, 非公平鎖的效能會優於公平鎖.
因為FairLock在獲取鎖時, 永遠是等待時間最長的執行緒獲取到鎖, 這樣當執行緒釋放鎖以後, 如果還想繼續再獲取鎖, 就必須去Sync佇列尾部進行排隊, 這樣就會發生頻繁的執行緒切換, 所以非公平鎖的吞吐量就要強於公平鎖
Benchmark
是openjdk提供一種基準測試的框架, 支援多種粒度的效能測試. 官方文件: https://github.com/openjdk/jmh
效能測試程式碼
利用CountDownLatch配合JMH, 測試極端條件下(獲取鎖之後立馬釋放鎖, 不斷迴圈), 不同的執行緒數量迴圈10000次加鎖解鎖的平均時間
@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
結論
從測試結果可以可看出, 非公平鎖的效能確實比公平鎖要好, 而且執行緒數量越多, 差別越是明顯