Contention in concurrent use of java.util.Random

房东的猫 提交于 2019-11-29 09:26:47
jcarvalho

Internally, java.util.Random keeps an AtomicLong with the current seed, and whenever a new random number is requested, there is contention in updating the seed.

From the implementation of 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));
}

On the other hand, ThreadLocalRandom ensures that the seed is updated without facing any contention, by having one seed per thread.

The random class holds a synchronisation lock around the internal state, such that only one thread can access it at once - specifically, it uses AtomicLong. This means that if you attempt to read from it with multiple threads, only one thread can access it at once, causing other threads to wait until the lock is released.

ThreadLocalRandom can be used instead to provide transparent per-thread instancing, to ensure that the internal state is updated on a per-thread basis, thus avoiding the lock.

Note that, if implemented correctly, the AtomicLong update operation shouldn't perform horribly unless you're running a huge number of threads, as it can essentially be optimised down within the JVM to something like lock xchg on x86. The major computational cost, outside of the lock, is likely a combination of the long multiply and rotational shift.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!