从多个线程使用 stdlib 的 rand()
Using stdlib's rand() from multiple threads
我有几个线程,它们都运行相同的函数。在每种情况下,它们都会多次生成不同的随机数。我们试图通过将srand(time(0))
放在函数的开头来实现这一点,但似乎它们都得到了相同的数字。
我们是否需要每个程序只调用srand(time(0))
一次,即在main
开始时(例如),在每个被调用多次的函数开始时,或者其他什么?
srand()为随机数生成器种子。您应该只需要在启动期间调用srand(time(NULL))
一次。
也就是说,文件指出:
函数
rand()
不可重入或线程安全,因为它使用隐藏每次调用时修改的状态。这可能只是被下一个调用使用,或者它可能做一些更精细的东西。整齐在线程应用程序,此状态必须明确。函数rand_r()
提供了一个指向CCD_。这是一个非常小的状态,所以这个函数将是一个弱函数伪随机生成器。尝试CCD_ 8(3)。
上面强调的部分可能是所有线程都得到相同数字的原因。
当您使用C++而不是C时,您可以通过使用C++11来避免通常与srand/rand相关的线程问题。这取决于使用支持这些功能的最新编译器。您将在每个线程上使用一个单独的引擎和分布。这个例子就像掷骰子一样。
#include <random>
#include <functional>
std::uniform_int_distribution<int> dice_distribution(1, 6);
std::mt19937 random_number_engine; // pseudorandom number generator
auto dice_roller = std::bind(dice_distribution, random_number_engine);
int random_roll = dice_roller(); // Generate one of the integers 1,2,3,4,5,6.
在回答这个问题时,我参考了维基百科C++11和Boost random。
来自rand
手册页:
函数rand()不是可重入的,也不是线程安全的,因为它使用的是每次调用都会修改的隐藏状态。
所以不要将它与线程代码一起使用。使用rand_r
(如果您在linux/glibc上,则使用drand48_r
)。为每个RNG设定不同的值(可以在主线程中设定第一个RNG的种子,为每个线程中的RNG生成随机种子)。
如果同时启动所有线程,则发送到srand的时间可能与每个线程相同。由于它们都有相同的种子,所以它们都返回相同的序列。尝试使用其他东西,比如本地变量中的内存地址。
C不是为多线程设计的,因此没有定义srand()的多线程行为,并且依赖于C运行库。
许多Unix/Linux C运行库使用单一静态状态,这对于从多个线程访问是不安全的,因此使用这些C运行库时,您根本无法从多个螺纹使用srand()和rand()。其他Unix C运行时的行为可能有所不同。
Visual C++运行时使用每个线程的内部状态,因此为每个线程调用srand()是安全的。但正如Neil所指出的,您可能会为所有具有相同值的线程进行种子处理,因此使用(time+thread-id)进行种子处理。
当然,为了便于移植,可以使用Random对象而不是rand函数,这样就完全不依赖于隐藏状态。每个线程仍然需要一个对象,用(time+thread-id)为每个对象播种仍然是个好主意。
这是个好问题。我不能直接回答,因为我认为还有更大的问题。似乎还不清楚rand是否是线程安全的。它维护内部状态,如果是按进程还是按线程,如果是线程安全的,则似乎没有很好地定义。
可以肯定的是,我会在每次访问时锁定一个互斥对象。
或者最好使用定义更好的生成,例如来自boost 的生成
- 为什么我不能将 rand() 与数组的大小一起使用?
- 带有 -stdlib=libc++ 的 clang++ 9.0.1 找不到<optional>
- 为什么新的随机库比std::rand()更好
- 为什么rand()的使用被认为是不好的
- C++使用 rand 定义函数语法
- 为什么 rand 不在我的代码中生成随机数?
- /usr/include/c++/7/cstdlib:75:15:致命错误:stdlib.h:没有这样的文件或目录 #i
- 为什么 CWE 认为 rand() 具有潜在危险
- 在 c++ 中,rand() 在执行有调试和不带调试的程序时生成不同的结果
- 在 xcode 上使用 stdlib.h
- 在 docker 容器之间传输时缺少 stdlib 符号
- Rand() 没有显示随机数,请帮助我了解出了什么问题:)
- Rand()大小写开关在多次迭代后运行到无穷大
- 75:15:致命错误:stdlib.h:没有这样的文件或目录 #include_next <stdlib.h>
- rand()函数在特定问题中的工作
- 为什么 someNumber = rand() & 100 + 1;不产生错误?
- 除了 rand() 之外,是否有任何随机生成器库,开发人员可以手动设置种子?
- 为什么stdlib中的rand不遵循大数定律
- 为什么c++ stdlib rand()函数在不同平台上对相同的种子给出不同的值?
- 从多个线程使用 stdlib 的 rand()