Is Random class thread safe?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
In Java, java.util.Random is thread-safe in the narrow sense that concurrent calls do not corrupt its internal state. That does not mean it is the best choice for multithreaded code. Shared use creates contention, and in practice ThreadLocalRandom or SplittableRandom is usually a better fit.
What "Thread-Safe" Means Here
Thread safety and performance are different questions. Random maintains internal mutable state, but its implementation coordinates access so multiple threads can call it without breaking the generator.
That means this is safe from a correctness perspective:
The program will work correctly. The issue is that the threads are all contending for one shared generator state.
Why Shared Random Performs Poorly
Even though the class is safe to call from multiple threads, a single shared instance becomes a bottleneck under concurrency. Each thread has to coordinate access to the same state transition logic, which reduces scalability.
If the application generates random values frequently from many threads, that contention can become measurable. The bigger the concurrency, the less attractive a single shared Random becomes.
So the right conclusion is:
- shared
Random: thread-safe but contended - not ideal for high-throughput concurrent generation
Use ThreadLocalRandom for Concurrent Application Code
For most multithreaded application code, ThreadLocalRandom is the standard replacement.
Each thread uses its own generator state, which avoids the shared-instance bottleneck.
Consider SplittableRandom for Parallel Algorithms
If you need strong performance in parallel numeric code or deterministic split-able generators, SplittableRandom is often better again.
This is particularly useful in fork/join-style workloads where independent random streams are desirable.
Do Not Confuse This With SecureRandom
Random and ThreadLocalRandom are not for security-sensitive randomness. If you need tokens, session identifiers, salts, or anything cryptographic, use SecureRandom.
Thread safety is not the deciding factor in that case. Security requirements are.
Choosing the Right Generator
A practical rule is:
- single-threaded or casual use:
Random - multi-threaded application code:
ThreadLocalRandom - parallel numeric workloads:
SplittableRandom - security-sensitive generation:
SecureRandom
This makes the design decision much clearer than asking only whether Random is "safe."
Common Pitfalls
The biggest mistake is assuming thread-safe automatically means performant. Random may be correct under concurrency while still being the wrong choice for throughput-heavy multithreaded code.
Another issue is creating a new Random repeatedly in tight loops. That hurts performance and can also create poor-quality sequences if done carelessly.
Developers also sometimes use Random or ThreadLocalRandom for security-sensitive values. Those classes are not designed for cryptographic unpredictability.
Finally, do not share a single Random everywhere out of habit. In concurrent code, ThreadLocalRandom.current() is usually simpler and faster.
Summary
- '
java.util.Randomis thread-safe for correctness, but a shared instance causes contention.' - '
ThreadLocalRandomis the usual choice for concurrent application code.' - '
SplittableRandomis useful for high-performance parallel workloads.' - '
SecureRandomis required for security-sensitive randomness.' - Ask both "is it safe" and "is it scalable" before choosing a random-number generator.

