并发使用java.util.Random时的争用

Tan*_*nay 12 java concurrency performance multithreading contention

Oracle Java文档说:

java.util.Random的实例是线程安全的.但是,跨线程并发使用相同的java.util.Random实例可能会遇到争用并因此导致性能不佳.请考虑在多线程设计中使用ThreadLocalRandom.

表现不佳背后的原因可能是什么?

小智 14

在内部,java.util.Random使用当前种子保留AtomicLong,并且每当请求新的随机数时,在更新种子时存在争用.

从java.util.Random的实现:

protected int next(int bits) {
    long oldseed, nextseed;
    AtomicLong seed = this.seed;
    do {
        oldseed = seed.get();
        nextseed = (oldseed * multiplier + addend) & mask;
    } while (!seed.compareAndSet(oldseed, nextseed));
    return (int)(nextseed >>> (48 - bits));
}
Run Code Online (Sandbox Code Playgroud)

另一方面,ThreadLocalRandom通过每个线程拥有一个种子来确保更新种子而不会遇到任何争用.