c# - 如何实现线程安全的随机数

标签 c# multithreading .net-core random cryptography

试图找到并理解在 .NET Core 2.x 或更高版本中实现线程安全数字生成器的最佳方法

我首先发现了这个 - https://web.archive.org/web/20160326010328/http://blogs.msdn.com/b/pfxteam/archive/2009/02/19/9434171.aspx

通读之后,我觉得有几个“好”的方法——

  1. ThreadStatic 随机实例,用全局随机实例生成种子
  2. ThreadStatic Random 实例,使用全局 RNGCryptoServiceProvider 生成种子

如果需要强加密随机性,基本上您会选择后者。

经过一些额外的研究,我发现自从 .NET Core 2.x System.Random 类被修改后,默认种子生成不再主要依赖于系统计时器。 ( https://blogs.siliconorchid.com/post/coding-inspiration/randomness-in-dotnet )

问题 - 这对线程安全随机类的实现有何影响?

引用第一个链接Iv'e共享代码解决方案-

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();
    }
}

由于 dotnet core 2.x 调整甚至需要全局锁定种子生成器?还是只需要一个基本的 ThreadStatic 随机实例?比如——

    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();
        }
    }

最佳答案

从 .NET 6 开始,您可以使用 Random.Shared 获取 Random 的线程安全实例。

文件是这样说的:

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

https://learn.microsoft.com/en-us/dotnet/api/system.random.shared?view=net-6.0

没有必要再花哨了。

要获得一个随机整数,您只需要做:

int number = Random.Shared.Next();

如果您想要密码学上的强随机性,那么 Eric Lippert 的 BetterRandom 是可行的方法:

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;
        }
    }
}

从这里开始阅读更多:https://ericlippert.com/2019/01/31/fixing-random-part-1/

关于c# - 如何实现线程安全的随机数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71238440/

相关文章:

c# - 在 OSX : "No assembly containing System.Object was found" 上使用 .NET Core 从代码调用 Roslyn

c# - 构建原生 C++ 库并在 WP8 应用程序中使用它

c# - .NET Core - 有没有办法在使用 Select Tag Heller 时将枚举设置为具有默认值?

java - Android 架构组件网络线程

java - Web应用程序中的线程安全

go - 两种不同语言之间的 Protocol Buffer

c# - Angular $http 错误响应 statusText 始终未定义

c# - 将 Func<IList, int> 传递给采用 Func<IEnumerable, int> 的方法?

c++ - 异步函数产生不一致的结果

asp.net-core - 当我在浏览器中刷新页面时,如何在 ASP.NET Core 2.2 中启用自动重建?