:::warning 参见: https://github.com/openjdk/jmh/blob/master/jmh-samples/src/main/java/org/openjdk/jmh/samples/JMHSample_15_Asymmetric.java :::

之前介绍的JMH全都是单线程的例子
但真正在生产中, 各种多线程并发的业务数不胜数
同样的代码, 在单线程中的执行效率,与多线程中截然不同, 不是简单的加一个线程速度就翻倍
如果多线程编程中竞态条件会极大的影响我们的执行效率

1. 例子

下面看一个模拟多线程竞争的代码

  1. @State(Scope.Group)
  2. @BenchmarkMode(Mode.Throughput)
  3. @OutputTimeUnit(TimeUnit.MICROSECONDS)
  4. public class Sample_15_Asymmetric {
  5. private AtomicInteger counter;
  6. @Setup
  7. public void up() {
  8. counter = new AtomicInteger();
  9. }
  10. @Benchmark
  11. @Group("benchmark_thread_competition")
  12. @GroupThreads(3)
  13. public int inc() {
  14. return counter.incrementAndGet();
  15. }
  16. @Benchmark
  17. @Group("benchmark_thread_competition")
  18. @GroupThreads(1)
  19. public int get() {
  20. return counter.get();
  21. }
  22. }

2. 分析

在这个例子中
inc() 与 get() 是两个方法, 虽然标记了两个 @Benchmark, 但他们是同时执行的
因为我们标记了 @Group(“benchmark_thread_competition”) , 他们在同一个组中
然后
inc() 同时会有3个线程执行
get()同时会有1个线程执行
整个过程中会启动4个线程执行

3. 报表

看看执行结果

  1. Benchmark Mode Cnt Score Error Units
  2. Sample_15_Asymmetric.benchmark_thread_competition thrpt 154.785 ops/us
  3. Sample_15_Asymmetric.benchmark_thread_competition:get thrpt 127.480 ops/us
  4. Sample_15_Asymmetric.benchmark_thread_competition:inc thrpt 27.305 ops/us

4. 对照组1

上面的例子是在竞争AtomicInteger对象的时候的执行效率

我们再来看看, 如果没有竞争的话, 执行效率如何

先看看单线程自增操作耗时

  1. @Benchmark
  2. @Group("benchmark_inc_no_competition")
  3. @GroupThreads(1)
  4. public int inc1() {
  5. return counter.incrementAndGet();
  6. }

单独一个线程, 执行inc()

  1. Benchmark Mode Cnt Score Error Units
  2. Sample_15_Asymmetric.benchmark_inc_no_competition thrpt 164.339 ops/us

发现没, 这个例子中只有一个线程, 但执行效率却远远超过上面三个线程同时inc的效率, 效率大概在6倍左右
多线程反而让执行效率降低了

5. 对照组2

再看看但线程get操作耗时

  1. @Benchmark
  2. @Group("benchmark_get_no_competition")
  3. public int get1() {
  4. // 这个benchmark只有一个线程在执行get操作
  5. // 效率直接拉满
  6. return counter.get();
  7. }
  1. Benchmark Mode Cnt Score Error Units
  2. Sample_15_Asymmetric.benchmark_get_no_competition thrpt 615.008 ops/us

执行效率是原来的5倍左右,

6. 总结

JMH对多线程的支持很完善, 提供了许多工具, 让我们有能力模拟真实的业务场景, 我们要善加利用