我正在阅读本节,最后一段指出示例代码不是线程安全的。我的问题是:这不会有助于增加它的随机性(即如果多个线程要同时执行这些行)?
4 回答
PRNG 是经过精心设计的(好吧,也许不是 RANDU),以产生可预测且足够随机分布的结果。它们不必是真正随机的,它们只需要满足统计质量测试,产生足够大的周期并且对相同的种子具有确定性。
如果您碰巧同时从多个线程使用生成器,那么所有这些保证都会付诸东流。最重要的是,您无法获得可重现的结果(这在模拟中极为重要)。然后状态可能会改变,或者你可能在不同的线程中两次获得相同的数字,那些事情。
你绝对不想去那里。每个线程创建一个 PRNG(最好使用线性独立的种子)。
非线程安全随机数生成器的一个可能副作用是您可以以某种方式破坏内部状态。例如,如果您Random
从两个不同的线程访问同一个 .NET 实例,则可以将其置于不断重复返回 0 的状态。
在您链接的 RNG 中,看起来不会发生特定问题,但某些退化的并发访问模式可能会设置m_z
或设置m_w
为 0,根据评论,这也很糟糕。
代码有多种方式是非线程安全的。
一种方法是线程无法看到其他线程对内存的写入。
然后我们可能会发现生成全零的随机数,因为它永远不会“看到”其他线程所做的工作。
您绝对可以从线程计时生成中获得熵,但是将熵收集和伪随机数生成混合在一起是一个非常糟糕的主意,因为前者可能会干扰后者的其他可证明的特性——就像 Joey 所说的那样。我添加新答案的原因是您可能会考虑将真实熵与您的 PRNG 混合(作为种子,或定期引入更多),并从不同线程收集真实时间信息是熵的一种可能来源。然而,它应该严格地完成(使用适当的锁定或无锁原子操作来存储结果),而不是通过调用未定义的行为并希望得到熵。