C#随机数生成器卡在一个循环中

Jea*_*rdi 5 c# random thread-safety

我正在使用.NET创建一个人工生命程序,我正在使用C#在Singleton中定义的伪随机类.我的想法是,如果我在整个应用程序中使用相同的随机数生成器,我只能保存种子,然后从种子重新加载以重新计算某个有趣的运行.

public sealed class RandomNumberGenerator : Random
{
    private static readonly RandomNumberGenerator instance = new RandomNumberGenerator();

    RandomNumberGenerator()
    {

    }

    public static RandomNumberGenerator Instance
    {
        get
        {
            return instance;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我还想要一个可以给我两个不同随机数的方法.

public static Tuple<int, int> TwoDifferentRandomNumbers(this Random rnd, int minValue, int maxValue)
    {
        if (minValue >= maxValue)
            throw new ArgumentOutOfRangeException("maxValue", "maxValue must be greater than minValue");
        if (minValue + 1 == maxValue)
            return Tuple.Create<int, int>(minValue, maxValue);

        int rnd1 = rnd.Next(minValue, maxValue);
        int rnd2 = rnd.Next(minValue, maxValue);
        while (rnd1 == rnd2)
        {                
            rnd2 = rnd.Next(minValue, maxValue);
        }
        return Tuple.Create<int, int>(rnd1, rnd2);            
    }
Run Code Online (Sandbox Code Playgroud)

问题是有时候rnd.Next(minValue,maxValue总会回来minValue.如果此时断点并尝试创建双精度并将其设置为rnd.NextDouble(),则返回0.0.任何人都知道为什么会这样吗?

我知道它是一个伪随机数生成器,但坦率地说,我没想到它会锁定为0.从多个线程访问随机数生成器......这可能是问题的根源吗?

编辑:谢谢,问题最终是线程安全.

这是该类的新版本.

 public sealed class RandomNumberGenerator : Random
{
    private static Random _global = new Random();
    [ThreadStatic]
    private static Random _localInstance;

    RandomNumberGenerator()
    {

    }

    public static Random Instance
    {
        get
        {
            Random inst = _localInstance;
            if (inst == null)
            {
                int seed;
                lock (_global) seed = _global.Next();
                _localInstance = inst = new Random(seed);
            }
            return _localInstance;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

SLa*_*aks 11

Random班是不是线程安全的.

你应该制作你的static实例[ThreadStatic],或用锁来保护它.


小智 3

如果您仅对多个线程使用一个 RNG,即使您保存了种子,您也将无法在下次启动应用程序时生成相同的数字,因为您无法确定从不同的地方对 RNG 的调用是否正确。线程将按相同的顺序排列。

如果您有固定/已知数量的线程,请为每个线程创建一个 RNG 并保存每个种子。

如果您 100% 确定每个线程都会以与上次使用相同种子时完全相同的顺序调用 RNG,请忘记我刚才所说的内容。