【发布时间】:2010-09-21 03:18:25
【问题描述】:
this question 被接受的答案,以及今天工作中的类似讨论让我想知道一些事情。
问题是关于如何在多线程程序中安全地生成随机数。公认的答案主张使用线程本地存储,有效地为每个线程创建一个随机数生成器。我想知道这是否真的是个好主意。
假设我们有两个线程同时启动(在多核系统上很可能)并且都调用默认的Random 构造函数来创建和初始化线程本地存储中的随机数生成器。由于他们没有传递种子参数,Random 使用系统时间作为种子。因此,两个随机数生成器都使用相同的种子进行了初始化。它们都将生成相同的随机数序列。
由于这些线程是从线程池中分配的,因此您无法将特定对象与特定线程相关联。或者,在上述问题的情况下,您无法保证哪个池线程将执行下一个请求。所以想象一下会发生以下情况:
At startup, two requests come in simultaneously.
Two threads are created, each initializing a random number generator with the same seed.
Each thread generates three random numbers. They will be identical in both threads.
Next request comes in. It's assigned to thread #1.
It generates a random number and exits.
Some period of time elapses.
Next request comes in. It's assigned to thread #2.
It generates the same random number that thread #1 did just a while ago.
这可能会无限期地持续下去,尽管我怀疑它会不会那么糟糕。关键是两个线程具有相同的 PRNG,并且重复序列的可能性非常高。我知道PRNG中的P代表“伪”,但这有点多。
我认为多个线程很有可能用相同的种子值初始化Random 实例。如果发生这种情况,那么应用程序中至少某些事物的“随机性”将会受到影响。当然,其含义取决于应用程序。
我不知道的是,如果 PRNG 使用不同的种子进行初始化,这是否会使客户端看到的序列更随机、更随机或大致相同?也就是说,如果我要写:
var rnd1 = new Random(123);
var rnd2 = new Random(654);
for (int i = 0; i < OneMillion; ++i)
{
numbers.Add(rnd1.Next());
numbers.Add(rnd2.Next());
}
与仅从任一 PRNG 中生成 200 万个数字相比,我生成的数字序列会更多还是更少随机?
【问题讨论】:
-
如果在每次运行时生成相同的随机数序列,对您的应用程序来说是否有问题?
-
@Nader:这个问题更多的是理论而不是实际,因为我并没有真正想到特定的应用程序。但是假设您的问题的答案是肯定的。
-
@sje397:更多.Net,我想说,虽然这个想法实际上并不是特定于平台的,因为任何使用线程池和线程本地存储的系统都会表现出这种行为。但由于我的示例是用 C# 编写的并且我使用 .Net 术语,所以我用 .net 标记了这个问题。
-
@Jim:那么在这种情况下,你不会想要对你的种子进行硬编码。否则,这是正确的想法......确保不同的生成器有不同的种子,你很高兴。或者,您可以使用不同的 RNG。
-
@Jim:它只适用于使用类似 RNG 的其他平台(即,仅依赖于提供的种子)。
标签: .net multithreading random