Random over ThreadLocalRandom

JavaMultithreadingRandom

Java Problem Overview


> Instances of java.util.Random are threadsafe. However, the concurrent > use of the same java.util.Random instance across threads may encounter > contention and consequent poor performance. Consider instead using > ThreadLocalRandom in multithreaded designs.

What kind of contention and thus poor performance ? Can anybody please, explain me here ? I don't know what algorithm goes inside Random and ThreadLocalRandom that makes them different.

Java Solutions


Solution 1 - Java

This might help a little:

http://thoughtfuljava.blogspot.com/2012/09/prefer-threadlocalrandom-over-random.html


Quoted from source:

Normally to generate random numbers, we either do create an instance of java.util.Random or Math.random() - which internally creates an instance of java.util.Random on first invocation. However, in a concurrent applications usage of above leads to contention issues.

Random is thread safe for use by multiple threads. But if multiple threads use the same instance of Random, the same seed is shared by multiple threads. It leads to contention between multiple threads and so to performance degradation.

ThreadLocalRandom is solution to above problem. ThreadLocalRandom has a Random instance per thread and safeguards against contention.


So, basically, using a random instance per thread allows you to stop synchronizing on the seed which must be used by all threads.

Solution 2 - Java

There are some problems with ThreadLocalRandom, that you cannot control the initial seed. I also don't find a working set seed method somewhere.

It should be noted that there is contention when multiple threads use Math.random(), since they will under the hood access a shared instance of the class Random, there is an alternative in using ThreadLocalRandom which also solves the seed problem.

ThreadLocalRandom uses a seed stashed into the Thread. And they decided to do the initial seed for you, without any means to control it. You can equally well create your own instance of Random and use it in a thread local fashion. So if you do the following:

/* my thread */
rnd = new Random(my_seed);
/* use rnd */

You will also see no contention. And using the same seed, you get reproducable random sequences, which can help in testing. When you have multiple threads you can distribute seeds over these threads. There should be algorithms around to generate good distance seeds.

Solution 3 - Java

The core algorithms are essentially the same. The ThreadLocalRandom uses the Java ThreadLocal construct to create a new Random variable for each thread. This guarantees that the calls from each thread will never conflict with each (no contention).

Take a look at this line from Random for comparison:

  } while (!seed.compareAndSet(oldseed, nextseed));

When you ask for a next value, Random takes the old value and generates a new value. It then uses the AtomicLong.compareAndSet function to set the new value, only if the old value is still the one it used. If another thread had changed the value, the loop will run again (and again, until it's the only loop that's both get and set the value in one random number generation). Thus there is possible contention, and thus possible performance implications.

The ThreadLocalRandom, because it is guaranteed not to conflict, does not require atomic functions and thread-safe operations/locking.

There are some tradeoffs you would want to think about. Using one Random allows for one random number generator which is very useful if you want to use a single seed for your application. If you make only occasional calls to Random, so that conflicts are likely to be "rare" (not the normal case) then you might not worry about conflicts and the small individual impact to performance may not matter. If you're calling random hundreds of time per seconds across multiple threads, then you clearly want to use ThreadLocalRandom.

Solution 4 - Java

Well, if you use the same data structure over multiple threads it has usually to be synchronized. This is expensive and needs time. A ThreadLocalRandom does not have to be synchronized as it is only used by one thread.

Solution 5 - Java

From ThreadLocalRandom API Document

A random number generator isolated to the current thread.  Like the
 * global {@link java.util.Random} generator used by the {@link
 * java.lang.Math} class, a {@code ThreadLocalRandom} is initialized
 * with an internally generated seed that may not otherwise be
 * modified. When applicable, use of {@code ThreadLocalRandom} rather
 * than shared {@code Random} objects in concurrent programs will
 * typically encounter much less overhead and contention.  Use of
 * {@code ThreadLocalRandom} is particularly appropriate when multiple
 * tasks (for example, each a {@link ForkJoinTask}) use random numbers
 * in parallel in thread pools.

Random can be created multiple times / same Random Object would shared across multiple threads ( due to the fact safe to use) . How ever creating multiple instance / same resource access by multiple thread would cause overhead.

Instead of Creating instance per Thread and maintain the resource in ThreadLocal would be more perfect. since the instance is not shared across multiple Threads. and there are no public constructor , your should use the factory method to get it.

I would say, it is just Factory of Random Objects which maintains /caches instance per thread.

Solution 6 - Java

A Random instance can only provide a random number to one thread at a time. So, if you have many threads simultaneously requesting random numbers from that instance, that tends to slow down all the threads.

On the other hand, each thread would have its own ThreadLocalRandom instance, so no threads would be blocked when requesting a random number.

Solution 7 - Java

Hope, this may help a little- Top 4 ways to Generate Random Numbers in Java


Random

Java Random class is used to generate a stream of pseudorandom numbers. The algorithms implemented by Random class use a protected utility method than can supply up to 32 pseudorandomly generated bits on each invocation.

  • doubles(): Returns an unlimited stream of pseudorandom double values.
  • ints(): Returns an unlimited stream of pseudorandom int values.
  • longs(): Returns an unlimited stream of pseudorandom long values.
  • next(): Generates the next pseudorandom number.

ThreadLocalRandom:

This random number generator isolated to the current thread. Like the global Random generator used by the Math class, a ThreadLocalRandom is initialized with an internally generated seed that may not otherwise be modified.

  • Using ThreadLocalRandom in concurrent programs will typically encounter much less overhead and contention than using the global Random class.

  • You can use ThreadLocalRandom when multiple tasks like a ForkJoinTask need random numbers in parallel in thread pools.

To Learn Better:

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser2031271View Question on Stackoverflow
Solution 1 - JavaJohn HumphreysView Answer on Stackoverflow
Solution 2 - Javauser502187View Answer on Stackoverflow
Solution 3 - Javauser1676075View Answer on Stackoverflow
Solution 4 - JavanilsView Answer on Stackoverflow
Solution 5 - JavaManiView Answer on Stackoverflow
Solution 6 - JavacybersamView Answer on Stackoverflow
Solution 7 - JavaSKLView Answer on Stackoverflow