【问题标题】:C# Random.Next suddenly stops returning random values [duplicate]C# Random.Next 突然停止返回随机值 [重复]
【发布时间】:2010-07-07 16:00:57
【问题描述】:

可能重复:
System.Random keeps on returning the same value

我正在重构和扩展一个基于 C# 代理的小型模型,以帮助一些生物学教授预测疾病的传播。模拟的每一年,每个个体随机移动到附近的人口节点,可能传播疾病。我是 C# 的新手,但我读过有关 Random.Next 的潜在问题,如果使用相同的系统时间重新初始化,则返回相同的值。为了避免这种情况,我创建了一个静态实例,每个新的随机值都会引用它。

具体情况:

在我努力扩大模型的过程中,我对其进行了更改,以并行计算每个人口节点的“旅行”信息。在测试模型时,我注意到在新版本中,疾病不会在第​​一年之后传播。进一步的调查将问题缩小到节点之间的旅行。第一年之后,所有特工都保持不动。我检查了负责他们旅行的函数,发现它通过创建所有附近节点的列表、生成随机数

问题:

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

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

有没有人知道我应该在哪里寻找错误?谢谢!

【问题讨论】:

  • 重现错误的简短而完整的代码示例将有助于您和 SO 社区帮助您诊断问题。
  • 我问了一个我认为相关且可能有帮助的问题:stackoverflow.com/questions/2924599/…

标签: c# random c#-4.0 return-value


【解决方案1】:

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

选项:

  • 为每个线程创建一个新的 Random 实例(ThreadStatic 可以在此处提供帮助)
  • 使用Random 的单个实例,但只能在锁中使用它。

我有一个带有一些示例代码的blog post,但请阅读 cmets 以及改进它的好建议。我计划在不久的将来写另一篇关于随机性的文章......

【讨论】:

    【解决方案2】:

    我不认为 Random 类被设计为线程安全的(可同时从多个线程中使用) - 因此,如果您以这种方式共享单个实例,您可能会破坏随机生成器的状态,从而阻止它无法正常运行。

    您可以将包含对 Random 类的引用的静态变量装饰为ThreadStatic,这将允许您为每个线程维护一个单独的实例:

    [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<T> 类,它有助于更​​轻松地为每个线程初始化一个实例。

    【讨论】:

      【解决方案3】:

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

      class ThreadSafeRandom 
      { 
          private static Random random = new Random(); 
      
          public static int Next() 
          { 
             lock (random) 
             { 
                 return random.Next(); 
             } 
          } 
      }
      

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

      【讨论】:

        【解决方案4】:

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-04-17
          • 2010-12-11
          • 2013-12-23
          • 2013-06-04
          • 2016-05-30
          • 1970-01-01
          相关资源
          最近更新 更多