Fixed multi-threading access to random

This commit is contained in:
Thorsten Sommer 2020-09-24 20:22:05 +02:00
parent 083c274818
commit e43738d976

View File

@ -15,6 +15,8 @@ namespace FastRng
private const int CAPACITY_RANDOM_NUMBERS_4_SOURCE = 16_000_000; private const int CAPACITY_RANDOM_NUMBERS_4_SOURCE = 16_000_000;
#endif #endif
private static readonly object SYNC = new object();
private readonly System.Random rng = new System.Random(); private readonly System.Random rng = new System.Random();
private readonly CancellationTokenSource producerToken = new CancellationTokenSource(); private readonly CancellationTokenSource producerToken = new CancellationTokenSource();
@ -63,22 +65,31 @@ namespace FastRng
// //
var buffer = new double[CAPACITY_RANDOM_NUMBERS_4_SOURCE]; var buffer = new double[CAPACITY_RANDOM_NUMBERS_4_SOURCE];
for (var n = 0; n < buffer.Length && !cancellationToken.IsCancellationRequested; n++)
//
// Random is not thread-safe!
// Because we using two threads, we ensure that one threads generates
// next bag of numbers while the other pumps its numbers into the channel.
//
lock (SYNC)
{ {
#region Re-implementation of GetSampleForLargeRange() method of .NET for (var n = 0; n < buffer.Length && !cancellationToken.IsCancellationRequested; n++)
{
#region Re-implementation of GetSampleForLargeRange() method of .NET
var result = random.Next(); // Notice: random.Next() is identical to InternalSample() var result = random.Next(); // Notice: random.Next() is identical to InternalSample()
var negative = random.Next() % 2 == 0; // Notice: random.Next() is identical to InternalSample() var negative = random.Next() % 2 == 0; // Notice: random.Next() is identical to InternalSample()
if (negative) if (negative)
result = -result; result = -result;
double d = result; double d = result;
d += (int.MaxValue - 1); // get a number in range [0 .. 2 * Int32MaxValue - 1) d += (int.MaxValue - 1); // get a number in range [0 .. 2 * Int32MaxValue - 1)
d /= 2 * (uint)int.MaxValue - 1; d /= 2 * (uint)int.MaxValue - 1;
#endregion #endregion
buffer[n] = d; buffer[n] = d;
}
} }
for (var n = 0; n < buffer.Length && !cancellationToken.IsCancellationRequested; n++) for (var n = 0; n < buffer.Length && !cancellationToken.IsCancellationRequested; n++)