【问题标题】:Random.Next() sometimes returns same number in separate threadsRandom.Next() 有时会在不同的线程中返回相同的数字
【发布时间】:2011-01-06 09:59:05
【问题描述】:

我有以下课程

class Program
{
   static Random _Random = new Random();

   static void Main(string[] args)
   {
      ...
      for (int i = 0; i < no_threads; ++i)
      {
         var thread = new Thread(new ThreadStart(Send));
         thread.Start();
      }
      ...   
   }

   static void Send()
   {
      ...
      int device_id = _Random.Next(999999);
      ...
   }
}

代码创建指定数量的线程,启动每个线程,并为每个线程分配一个随机的device_id。出于某种原因,创建的前两个线程通常具有相同的device_id。我不明白为什么会这样。

【问题讨论】:

  • 这在统计上是正确的,就好像你掷 2 个骰子,它们有时会给你相同的数字,而且 Random 不是线程安全的 -> blogs.msdn.com/b/pfxteam/archive/2009/02/19/9434171.aspx
  • @Mitch:所有链接的问题都没有处理相同的情况。这里只有线程安全相关,因为只有一个 Random 实例。
  • @Jon:是的,没错。
  • 从表面上看,如果两个线程以相同的 device_id 结束,这会给您带来问题。如果是这种情况,那么您无论如何都不应该使用 random 分配 - 您应该做一些 保证 没有冲突的事情。
  • @dvvh:是的,但是内部间隔足够大,因此每隔一次运行就不会发生碰撞。问题已经解决了。

标签: c# multithreading random


【解决方案1】:

Random 不是线程安全的 - 您不应该使用来自多个线程的同一个实例。它可能比仅仅返回相同的数据更糟糕 - 通过从多个线程中使用它,您可以让它“卡”在它总是返回 0,IIRC 的状态。

显然,您不只是想大致同时为每个线程创建一个新实例,因为它们最终会得到相同的种子...

我有一个article,它详细介绍了这一点,并提供了一个实现,它使用递增的种子懒惰地为每个线程实例化一个Random 实例。

【讨论】:

  • 我很怀疑,但即使在查看 MSDN 之后也不确定。我也会看看你的文章。谢谢。
  • 另见 Jon Skeet 的MiscUtil.StaticRandom
【解决方案2】:

Random 是一个伪随机数生成器,没有什么可以阻止它为多次调用返回相同的结果。毕竟这种情况是有可能发生的。更不用说根据documentation

不保证任何实例成员都是线程安全的。

因此,您根本不应该从多个线程调用 Next 方法。

【讨论】:

    【解决方案3】:

    您的示例代码仅显示每个线程使用一次_Random。假设是这种情况,您还可以在 for 主循环中生成随机数,并将随机数作为参数传递给每个线程。

     for (int i = 0; i < no_threads; ++i)
     {
          var thread = new Thread(new ThreadStart(Send));
          thread.Start(_Random.Next(999999));
     }
    

    然后修改你的线程函数来接受参数:

     static void Send(int device_id)
     {
        ...
        //int device_id = _Random.Next(999999);
        ...
     }   
    

    【讨论】:

      猜你喜欢
      • 2015-09-28
      • 2011-07-12
      • 2013-04-17
      • 2010-12-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多