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.