Skip to content

Commit

Permalink
random: Add note about global rng
Browse files Browse the repository at this point in the history
  • Loading branch information
rmandvikar committed Mar 10, 2023
1 parent d1dbab3 commit 88eb5a0
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Random doesn't inherit from an interface so the implementations inherit from Ran

`LockRandom` simply makes pass-through calls to the base instance's methods with a lock, so using a specific seed technically is possible but not done.

`ThreadStaticRandom` and `ThreadLocalRandom` use similar approaches where a global RNG is used to seed the threads' Random instances. A specific seed is meaningless and the base instance is unused. The global RNG implementations are not exactly the same so as to keep them as the original authors intended.
`ThreadStaticRandom` and `ThreadLocalRandom` use similar approaches where a global RNG is used to seed the threads' Random instances. A specific seed is meaningless and the base instance is unused. In previous versions, the global RNG implementations were not exactly the same so as to keep them as the original authors intended, but using a cryptographic RNG for the global seed is better.

To address the shortcomings, a static member with thread-safe impl as `Random.Shared` was added in `net6.0`. It uses `ThreadStatic` underneath ([see pr](https://github.com/dotnet/runtime/pull/50297/files#diff-6fa7e54f57878bb019a11332aeeb42c75430a0ac87c78cdfa9ce382137b3d851)).

Expand Down
13 changes: 13 additions & 0 deletions src/rm.Random2/RandomUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,19 @@ public static class RandomUtils
/// </summary>
public static Random NewRandom()
{
// see https://devblogs.microsoft.com/pfxteam/getting-random-numbers-in-a-thread-safe-way/
// Of course, if you really care about the quality of the random numbers, you should be
// using RNGCryptoServiceProvider, which generates cryptographically-strong random
// numbers (Addendum: davidacoder makes a good point in his comments on this post that
// while Random has certain statistical properties, using multiple Random instances as
// part of the same algorithm may change the statistical properties in unknown or
// undesirable ways). For a look at how to get a Random-based facade for RNGCryptoServiceProvider,
// see .NET Matters: Tales from the CryptoRandom in the September 2007 issue of MSDN Magazine.
// You could also settle on an intermediate solution, such as using an RNGCryptoServiceProvider
// to provide the seed values for the ThreadStatic Random instances in a solution like
// that in RandomGen2 (which would help to avoid another issue here, that of two threads
// starting with the same seed value due to accessing the global Random instance in the
// same time quantum).
const int bytesCount = 4;
#if NET6_0_OR_GREATER
byte[] buffer = RandomNumberGenerator.GetBytes(bytesCount);
Expand Down

0 comments on commit 88eb5a0

Please sign in to comment.