C#Random.Next突然停止返回随机值

C# Random.Next suddenly stops returning random values

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
System.Random keeps on returning the same value

我正在重构和扩展一个基于代理的小型模型,以帮助一些生物学教授预测疾病的传播。在每年的模拟中,每一个单独的药剂都随机地移动到附近的人口节点,可能传播疾病。我对C是全新的,但我已经读过随机的潜在问题。接下来,如果用相同的系统时间重新初始化,则返回相同的值。为了避免这种情况,我创建了一个静态实例,它被每个新的随机值引用。

具体情况:

在我扩大模型的努力中,我改变了它,以并行计算每个人口节点的"旅行"信息。在测试这个模型时,我注意到在新版本中,疾病不会在第一年后传播。进一步的调查将问题缩小到节点之间的行程。第一年之后,所有的特工都不动了。我检查了负责它们运行的函数,发现它是通过创建一个所有附近节点的列表,生成一个随机数<=列表中元素的数量,并运行到ListofNearByNodes[MyrandomNumber]来工作的。

问题:

然后我添加了一个print语句来输出每个迭代的随机索引的值。我发现整个模型在模拟的第一年中完全按照预期工作,随机数在一个可接受的范围内生成。但是,在第一年结束并且模拟循环之后,完全相同的代码将只返回0的"随机"索引。每个线程,每个迭代,每个节点,每个代理,总是0。由于代理的当前节点始终是列表中的第一个项目,因此代理不会再次移动。

我认为这可能是系统时间种子错误的另一种表现形式,所以我尝试了三种不同的方法来实现静态随机对象,但没有帮助。每次我运行模拟时,第一年总是正确运行,然后随机运行。next()开始只返回0。

有人知道我下一步应该在哪里寻找这个bug吗?谢谢!


我怀疑您在多个线程中同时使用同一个Random实例。不要这样做-这不是线程安全的。

选项:

  • 为每个线程创建一个新的Random实例(ThreadStatic在这里有帮助)
  • 使用EDOCX1的单个实例(0),但只能在锁中使用它。

我有一篇博客文章,上面有一些示例代码,但是请阅读评论,并有一些改进的好建议。我打算在不久的将来写另一篇关于随机性的文章…


我不相信随机类被设计成线程安全的(同时可从多个线程使用)-因此,如果您以这种方式共享一个实例,您可能会损坏随机生成器的状态,从而阻止它正确运行。

您可以将保存对随机类引用的静态变量修饰为ThreadStatic,这将允许您为每个线程维护单独的实例:

1
2
3
4
5
6
7
8
[ThreadStatic]
private static Random m_Random;  // don't attempt to initialize this here...

public void YourThreadStartMethod()
{
    // initialize each random instance as each thread starts...
    m_Random = new Random();
}

如果您使用的是.NET 4.0,那么还有ThreadLocal类,这有助于使每个线程初始化一个实例更加容易。


Random对象不是线程安全的。为了解决这个问题,您可以使用从这个答案中窃取的代码:

1
2
3
4
5
6
7
8
9
10
11
12
class ThreadSafeRandom
{
    private static Random random = new Random();

    public static int Next()
    {
       lock (random)
       {
           return random.Next();
       }
    }
}

您还可以使用RNGCryptoServiceProvider,它是线程安全的,而且可以产生更好的随机数据。


我认为您应该使用RNGCryptoServiceProvider

http://msdn.microsoft.com/en-us/library/system.security.cryptography.rngcryptoserviceprovider.aspx