Is it valid to share one instance of the Random
class between multiple threads? And to call nextInt(int)
from multiple threads in particular?

- 5,979
- 7
- 44
- 53
-
Care using Random to get numbers in a multithread environment can give you bad results.Maybe it does not matter but if you are doing some simulations it is good to know. – Maxence SCHMITT Apr 28 '11 at 13:59
-
15For further readers: there is a new class with 1.7 named `java.util.concurrent.ThreadLocalRandom`. – Jin Kwon Nov 16 '12 at 01:30
-
Beware of [Contention in concurrent use of java.util.Random](https://stackoverflow.com/questions/22313552/contention-in-concurrent-use-of-java-util-random). – Vadzim Jun 27 '18 at 22:07
8 Answers
It is thread safe in the sense it will still generate random numbers when used by multiple threads.
The Sun/Oracle JVM implementation uses synchronized and AtomicLong as seed to improve consistency across threads. But it doesn't appear to be guarenteed across all platforms in the documentation.
I wouldn't write your program to require such a guarantee, especially as you cannot determine the order in which nextInt()
will be called.

- 87,898
- 29
- 167
- 228

- 525,659
- 79
- 751
- 1,130
-
76A guarantee has been added in the Java 7 docs: "Instances of java.util.Random are threadsafe." http://docs.oracle.com/javase/7/docs/api/java/util/Random.html – Matt R Jul 12 '13 at 14:38
It is thread safe, although it wasn't always.
See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6362070 for more details.

- 4,059
- 2
- 21
- 26
Acording to the Java 6 documentation, Math.random() guarantees it's safe for use by multiple threads. But the Random class does not. I would assume then you'll have to synchronize that yourself.
EDIT:
According to the accepted answer, though, the documentation seems to have changed since Java 7 and the Random class seems to offer that guarantee too.

- 28,208
- 16
- 81
- 124
-
Under java 1.8 (RedHat OpenJDK), the Math.random() implementation looks like this: ```java public static double random() { return RandomNumberGeneratorHolder.randomNumberGenerator.nextDouble(); } // ... private static final class RandomNumberGeneratorHolder { static final Random randomNumberGenerator = new Random(); } ``` I can't figure out how it can be considered thread-safe while java.util.Random is not... – Marco Carlo Moriggi Aug 12 '21 at 15:01
-
1« According to the documentation » - not « according to what I saw in the implementation ». Implementation details could vary, I just stick to what the documentation says. According to the accepted answer, though, the documentation seems to have changed since Java 7 and the Random class seems to offer that guarantee too. – Vincent Mimoun-Prat Sep 02 '21 at 09:25
Yes, Random is thread safe. the nextInt()
method calls the protected next(int)
method which uses AtomicLong seed, nextseed
(atomic long) to generate a next seed. AtomicLong
is used for thread-safety upon seed generation.

- 87,898
- 29
- 167
- 228
As said, it is thread save, but it may be wise to use java.util.concurrent.ThreadLocalRandom
according to this article (link dead). ThreadLocalRandom is also a subclass of Random, so it is backwards compatible.
The article linked compared profiling results of the different Random classes:
java.util.Random
,java.util.concurrent.ThreadLocalRandom
andjava.lang.ThreadLocal<java.util.Random>
. The results showed, that the usage of ThreadLocalRandom is most performant, followed by ThreadLocal and worst performing Random itself.

- 161
- 3
- 8
There's no reason multiple threads can't all use the same Random. However, since the class is not explicitly thread-safe and maintains a sequence of pseudo-random numbers via the seed. Multiple threads may end up with the same random number. It would be better to create multiple Randoms for each thread and seed them differently.
EDIT: I've just noticed that the Sun implementation uses AtomicLong so i guess that is Thread-safe (as also noted by Peter Lawrey (+1)).
EDIT2: OpenJDK also uses AtomicLong for the seed. As others have said though it's still not good to rely on this.

- 4,668
- 1
- 18
- 19
Here's how I dealt with the problem without assuming that Random uses atomic variables. It can still randomly collide if currentTime * thread id
is equal some time in the future, but that's rare enough for my needs. To truly avoid the possibility of collisions, you could have each request wait for a unique clock timestamp.
/**
* Thread-specific random number generators. Each is seeded with the thread
* ID, so the sequence of pseudo-random numbers are unique between threads.
*/
private static ThreadLocal<Random> random = new ThreadLocal<Random>() {
@Override
protected Random initialValue() {
return new Random(
System.currentTimeMillis() *
Thread.currentThread().getId());
}
};

- 1,171
- 1
- 10
- 23
-
-
1Yeah, that was a dirty fix. The `(24*60*60*1000)` was so that a thread with ID `12` at `xxxxxxxxxx045` millis didn't get seeded the same as a thread `22` at `xxxxxxxxxx035` millis. However I don't have any good reason to assume that thread IDs are incremental, and there's no good reason to think I'm creating threads at more random times tomorrow than today. I simplified the alg now and updated the description to identify the shortcoming. – Ryan Nov 15 '12 at 23:29
The Random
class is not set up for one instance to be used in multiple threads. Ofcourse, if you did this, likely you will increase the possibility of getting un-predictable and closer to random numbers. But since it is a pseudo-random generator, I cannot see why you would need to share an instance. Is there a more specific requirement?

- 3,127
- 1
- 21
- 19