Random.Next()有时会在不同的线程中返回相同的数字

时间:2011-01-06 09:59:05

标签: c# multithreading random

我有以下课程

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。我无法弄清楚为什么会这样。

3 个答案:

答案 0 :(得分:26)

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

显然,您不仅希望在大致相同的时间为每个线程创建一个新实例,因为它们最终将使用相同的种子...

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

答案 1 :(得分:5)

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

  

不保证所有实例成员都是线程安全的。

所以你不应该从多个线程中调用Next方法。

答案 2 :(得分:2)

您的示例代码仅显示每个线程使用_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);
    ...
 }