If I run this test:
var r = new Random();
var ints = new int[13];
Parallel.For(0, 2000000, i => {
var result = r.Next(1, 7) + r.Next(1, 7)
In addition to @spencerruport's assertion that the Random class is not thread safe, your parallel code is also not threadsafe:
Parallel.For(0, 2000000, i => {
//say two threads produce same total at same time
var result = r.Next(1, 7) + r.Next(1, 7);
//what happens on the next line when a context-switch
//occurs during this non-atomic operation?
ints[result] += 1;
});
It might be better to leverage PLINQ to do the collecting of results on your behalf:
Enumerable.Range(0, 2000000)
.AsParallel()
.Select(_ => SafeRandom(1, 7) + SafeRandom(1, 7))
.GroupBy(x => x)
.Select(g => new {value = g.Key, frequency = g.Count()})
instead of managing access to shared memory (your ints
array above) yourself.
A reasonable implementation of SafeRandom
might look something like this:
private static int seedUnique=0;
private static ThreadLocal tlRand=new ThreadLocal(() => {
var x=Interlocked.Add(ref seedUnique, 93459872);
var r=new Random((int)(DateTime.UtcNow.Ticks + x));
return r;
});
public static int SafeRandom(int min, int max)
{
return tlRand.Value.Next(min,max);
}