java - java 中的显式锁定与内在锁定降级

标签 java multithreading concurrency locking benchmarking

我有两个几乎相同的类来查找下一个斐波那契数。区别在于,其中一种使用内在锁定,另一种使用显式锁定。固有锁定实现比显式锁定快得多,也比 STM 或无锁实现快得多。

Impl/Threads      | 1      | 2      | 4      | 8      | 16     |
---               | ---    | ---    | ---    | ---    | ---    |
IntrinsicLocking  | 4959   | 3132   | 3458   | 3059   | 3402   |
ExplicitLocking   | 4112   | 5348   | 6478   | 12895  | 13492  |
STM               | 5193   | 5210   | 4899   | 5259   | 6733   |
LockFree          | 4362   | 3601   | 3660   | 4732   | 4923   |

该表显示了单次计算下一个斐波那契数的平均时间。在java 8和7上测试。代码放在github上https://github.com/f0y/fibench/tree/master/src/main/java/fibonacci/mdl

有人可以解释为什么内在锁定实现会获胜吗?

最佳答案

该基准在很多层面上都是错误的,目前讨论结果没有意义。

这是简单的 JMH 基准测试:

package fibonacci.bench;

import fibonacci.mdl.ExplicitLocking;
import fibonacci.mdl.FibonacciGenerator;
import fibonacci.mdl.IntrinsicLocking;
import fibonacci.mdl.LockFree;
import fibonacci.mdl.STM;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.GenerateMicroBenchmark;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;

import java.math.BigInteger;

/*
   Implementation notes:

   * This benchmark does not exhibit a steady state, which means
     we can not do timed runs. Instead, we have to time single
     invocations; therefore preset benchmark mode.

   * Each iteration should start from the pristine state,
     therefore we reinitialize in @Setup(Iteration).

   * Since we are interested in performance beyond the first
     invocation, we have to call several times and aggregate
     the time; this is why we have batchSize > 1. Note the
     performance might be different depending on given batch
     size.

   * Since we have to provide warmup, we do many iterations.

   * The performance is different run to run, because we are 
     measuring sometimes undeterministic thread allocations.
     JMH does it for us, hence multiple forks.

   * We don't want the profiles for difference FibonacciGenerator
     to mix up. JMH already takes care of that for us by forking
     each test.
     */

@BenchmarkMode(Mode.SingleShotTime)
@Warmup(iterations = 100, batchSize = JmhBench.BATCH_SIZE)
@Measurement(iterations = 100, batchSize = JmhBench.BATCH_SIZE)
@State(Scope.Benchmark)
public class JmhBench {

    public static final int BATCH_SIZE = 50000;

    private FibonacciGenerator explicitLock;
    private IntrinsicLocking intrinsicLock;
    private LockFree lockFree;
    private STM stm;

    @Setup(Level.Iteration)
    public void setup() {
        explicitLock = new ExplicitLocking();
        intrinsicLock = new IntrinsicLocking();
        lockFree = new LockFree();
        stm = new STM();
    }

    @GenerateMicroBenchmark
    public BigInteger stm() {
        return stm.next();
    }

    @GenerateMicroBenchmark
    public BigInteger explicitLock() {
        return explicitLock.next();
    }

    @GenerateMicroBenchmark
    public BigInteger intrinsicLock() {
        return intrinsicLock.next();
    }

    @GenerateMicroBenchmark
    public BigInteger lockFree() {
        return lockFree.next();
    }

}

在我的 Linux x86_64、JDK 8b129 和四个线程上,它产生:

Benchmark                      Mode   Samples         Mean   Mean error    Units
f.b.JmhBench.explicitLock        ss       100     1010.921       31.117       ms
f.b.JmhBench.intrinsicLock       ss       100     1121.355       20.386       ms
f.b.JmhBench.lockFree            ss       100     1848.635       83.700       ms
f.b.JmhBench.stm                 ss       100     1893.477       52.665       ms

关于java - java 中的显式锁定与内在锁定降级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22224237/

相关文章:

java - 找不到包或没有 package-info.java

.net - 使用特定 DLL 库时内存分配非常高。或许。不知道该怎么办

java - 共享队列 VS Actor 模型

java - 分布式 Spring REST 服务中的线程安全

java - thymeleaf 中的 if 语句

java - 如何像javascript一样设置java对象属性

java - 做某事,如果花费的时间超过 x 秒,则继续执行下一个任务

c# - 如何停止其 `DoWork` 处理程序仅包含一个(长时间运行)语句的BackgroundWorker?

java - 如何在实现可运行的两个子类之间共享一个变量

Java多线程问题——消费者/生产者模式