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

发布于 2025-01-09 22:10:10 字数 1789 浏览 0 评论 0原文

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

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

阅读完后在我看来,有几种“好”方法 -

  1. ThreadStatic Random 实例,带有全局随机实例来生成种子
  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();
        }
    }

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

月下客 2025-01-16 22:10:10

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

文件是这样说的:

提供一个线程安全的 Random 实例,可以在任何线程中同时使用。

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/

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://learn.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/

乖乖 2025-01-16 22:10:10
  1. System.Random 类在使用默认构造函数实例化时使用的算法已更改为新算法,但该类仍然不是线程安全的,因此旧技术如使用 [ThreadStatic] 仍然需要。
  2. 在 .NET Core 中,默认种子值由线程静态的伪随机数生成器生成。 这意味着您不再需要实现全局种子生成器。
  3. 当您确实想确保随机数安全时,请使用RandomNumberGenerator。例如,如果您只想显示随机的每日消息,请使用 System.Random,但如果您想生成随机秘密字符串,请使用 RandomNumberGenerator
  1. The algorithm the System.Random class use when instantiated with default constructor has changed to the new one, but the class is still not thread-safe, so old technique like using [ThreadStatic] is still needed.
  2. In .NET Core, the default seed value is produced by the thread-static, pseudo-random number generator. That means you don't need to implement global seed generator anymore.
  3. Use RandomNumberGenerator when you really want to make sure your random number is secure. For example, if you just want to display random daily messages, use System.Random, but if you want to generate a random secret string, use RandomNumberGenerator.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文