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

问题描述 投票:0回答:3

我有以下课程

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
。我不明白为什么会发生这种情况。

c# multithreading random
3个回答
28
投票

注意:从 .NET 6 开始,最合适的方法是使用线程安全的Random.Shared


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

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

我有一篇文章详细介绍了这一点,并提供了一种实现,该实现使用递增种子延迟实例化每个线程的一个

Random
实例。


5
投票

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

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

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


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);
    ...
 }   
© www.soinside.com 2019 - 2024. All rights reserved.