I am using C# Random to generate random numbers in a multi threaded scenario. According to the recommendation here by microsoft, I am using a static shared Random object for all the callers and is calling random.Next in a lock.
private static TimeSpan GetRandomJitter(IReadOnlyCollection<TimeSpan> timeSpans)
{
lock (s_randomizerLock)
{
int random = s_randomizerAcrossTenants.Next(timeSpans.Count);
return timeSpans.ElementAt(random);
}
}
But in the example Microsoft provided in the same page, They are using an additional check to see if the random is corrupted even then they have a lock for the usages of Next()
private void GetRandomNumbers(Object o)
{
CancellationToken token = (CancellationToken) o;
double result = 0.0;
countdown.AddCount(1);
try {
for (int ctr = 0; ctr < 2000000; ctr++)
{
// Make sure there's no corruption of Random.
token.ThrowIfCancellationRequested();
lock (randLock) {
result = rand.NextDouble();
}
// Check for corruption of Random instance.
if ((result == previous) && result == 0) {
source.Cancel();
}
else {
previous = result;
}
perThreadCtr++;
perThreadTotal += result;
}
Console.WriteLine("Thread {0} finished execution.",
Thread.CurrentThread.Name);
Console.WriteLine("Random numbers generated: {0:N0}", perThreadCtr);
Console.WriteLine("Sum of random numbers: {0:N2}", perThreadTotal);
Console.WriteLine("Random number mean: {0:N4}\n", perThreadTotal/perThreadCtr);
// Update overall totals.
lock (numericLock) {
totalCount += perThreadCtr;
totalValue += perThreadTotal;
}
}
catch (OperationCanceledException e) {
Console.WriteLine("Corruption in Thread {1}", e.GetType().Name, Thread.CurrentThread.Name);
}
finally {
countdown.Signal();
}
}
}
Why would they need a check for corruption? What might be a real life case for checking for Random corruption when I can make sure that all the usages to Random.Next() is locked by a randomizer lock?
How do we mitigate if my shared/static Random
get corrupted?
Is there any recommendation around this?