The accepted answer to this question, and a similar discussion at work today got me to wondering about something.
The question was about how to safely generate random numbers in a multi-threaded program. The accepted answer advocates using thread local storage, effectively creating one random number generator per thread. I wonder if that's really such a good idea.
Let's say we have two threads start up at the same time (quite possible on a multi-core system) and both call the default Random
constructor to create and initialize a random number generator in thread local storage. Since they didn't pass a seed parameter, Random
uses the system time as the seed. So both random number generators have been initialized with the same seed. They will both generaete the same sequence of random numbers.
Since these threads are allocated from the thread pool, there's no way you can associate a particular object with a particular thread. Or, in the case of the above-referenced question, you can't guarantee which pool thread will execute the next request. So imagine that the following happens:
At startup, two requests come in simultaneously.
Two threads are created, each initializing a random number generator with the same seed.
Each thread generates three random numbers. They will be identical in both threads.
Next request comes in. It's assigned to thread #1.
It generates a random number and exits.
Some period of time elapses.
Next request comes in. It's assigned to thread #2.
It generates the same random number that thread #1 did just a while ago.
This could continue indefinitely, although I doubt it would be ping-ponging quite that badly. The point is that both threads have the same PRNG and the likelihood of repeating a sequence is very high. I understand that the P in PRNG stands for "pseudo", but this is a bit much.
I think it's quite possible for multiple threads to initialize a Random
instance with the same seed value. If that happens, then the "randomness" of at least some things in the application is going to suffer. The implications of that, of course, are application dependent.
What I don't know is, if the PRNGs are initialized with different seeds, does that make the sequence seen by a client more random, less random, or about the same? That is, if I were to write:
var rnd1 = new Random(123);
var rnd2 = new Random(654);
for (int i = 0; i < OneMillion; ++i)
{
numbers.Add(rnd1.Next());
numbers.Add(rnd2.Next());
}
Would the sequence of numbers I generate be more or less random than if I were to just generate two million from either of the PRNGs?