Resolved: How to implement a thread-safe random

Question:

Trying to find and understand the best approach to implement a thread-safe number generator in .NET Core 2.x or higher
First Iv’e found this – https://web.archive.org/web/20160326010328/http://blogs.msdn.com/b/pfxteam/archive/2009/02/19/9434171.aspx
After reading through it seems to me like there are couple of “good” ways –
  1. ThreadStatic Random instance, with a global random instance to generate seeds
  2. ThreadStatic Random instance, with a global RNGCryptoServiceProvider to generate seeds

Where basically you choose the latter if a strong cryptographically random is a requirement.
After some additional research I found out that since .NET Core 2.x System.Random class was revised, therefore the default seed generation which is no longer primary dependent on the system timer. (https://blogs.siliconorchid.com/post/coding-inspiration/randomness-in-dotnet)
Question – How does this affect the implementation of a thread-safe random class?
Refrencing the first link Iv’e shared code solution –
public static class RandomGen2
{
    private static Random _global = new Random();
    [ThreadStatic]
    private static Random _local;

    public static int Next()
    {
        Random inst = _local;
        if (inst == null)
        {
            int seed;
            lock (_global) seed = _global.Next();
            _local = inst = new Random(seed);
        }
        return inst.Next();
    }
}
Since dotnet core 2.x adjustments is a global locked seed generator even required? or a basic ThreadStatic random instance is all thats needed? such as –
    public static class ThreadSafeRandom
    {
        [ThreadStatic]
        private static Random _local;

        public static int Next()
        {
            Random inst = _local;
            if (inst == null)
            {
                _local = inst = new Random();
            }
            return inst.Next();
        }
    }

Answer:

From .NET 6 you can use Random.Shared to get a thread-safe instance of Random.
The documents say this:

Provides a thread-safe Random instance that may be used concurrently from any thread.


https://docs.microsoft.com/en-us/dotnet/api/system.random.shared?view=net-6.0
There’s no need to get fancy anymore.
To get a random integer you just need to do:
int number = Random.Shared.Next();
If you want cryptographically strong randomness, then Eric Lippert’s BetterRandom is the way to go:
public static class BetterRandom
{
    private static readonly ThreadLocal<System.Security.Cryptography.RandomNumberGenerator> crng = new ThreadLocal<System.Security.Cryptography.RandomNumberGenerator>(System.Security.Cryptography.RandomNumberGenerator.Create);
    private static readonly ThreadLocal<byte[]> bytes = new ThreadLocal<byte[]>(() => new byte[sizeof(int)]);
    public static int NextInt()
    {
        crng.Value.GetBytes(bytes.Value);
        return BitConverter.ToInt32(bytes.Value, 0) & int.MaxValue;
    }
    public static double NextDouble()
    {
        while (true)
        {
            long x = NextInt() & 0x001FFFFF;
            x <<= 31;
            x |= (long)NextInt();
            double n = x;
            const double d = 1L << 52;
            double q = n / d;
            if (q != 1.0)
                return q;
        }
    }
}
Start here to read more: https://ericlippert.com/2019/01/31/fixing-random-part-1/

If you have better answer, please add a comment about this, thank you!