我正在编写一个程序,它会在循环中生成大量随机数。我试图让这些数字更难以预测(不仅是为了安全,而是为了避免多线程上的冲突)。
我注意到许多文档建议在程序中只调用一次srand
。例如:Random numbers in C,所选答案为“作为一般规则,在程序中只调用一次srand()”。
但为什么呢?做这样的事情为什么会这么糟糕:
int THIS_THREAD_SEED;
int randomness() {
++THIS_THREAD_SEED;
int i;
for(i=0 i<1000; i++) {
unsigned n = rand_r(&THIS_THREAD_SEED) / RAND_MAX;
/* do something with n */
}
return 0;
}
int do_something() {
int i;
for(i=0; i<1000; i++) {
randomness();
}
}
因此,每个函数调用一次更改种子,而不是每个程序更改一次。这样,无论运行多少个线程,没有两个线程都会有相同的随机数列表......对吗?
更新 假设我为每个线程都有一个唯一的种子,或者在全局SEED上使用互斥量来防止竞争条件。
答案 0 :(得分:2)
如果您在访问随机数生成器时担心竞争条件,请创建互斥或其他同步原语以避免此情况。
如果您考虑多次致电srand()
,请不要。这背后的原因是随机生成器初始化程序,它根据种子设置变量具有更差的随机特性,比随机发生器本身的性能更差,不应该用作替代。
答案 1 :(得分:1)
srand()
重置将为您生成的数字流rand()
。
来自srand的手册:
The srand() function sets its argument as the seed for a new sequence of pseudo-random integers to be returned by rand(). These sequences are repeatable by calling srand() with the same seed value.
如果您需要“更好”的随机数,那么rand()会让您查看其他随机来源。
同样srand()
不用于rand_r()
,而是使用您提供的参数(rand_r()
)。
如果你想在多个线程中使用rand_r()
,所有线程都应该有一个本地种子,你不应该使用一个全局变量。
rand()
的替代方案可以是Mersenne Twister
但如果您需要“真正的”随机性,您必须寻求硬件支持。
并回答:
因此,每个函数调用一次更改种子,而不是每个程序更改一次。这样,无论运行多少个线程,没有两个线程都会有相同的随机数列表......对吗?
不,不这样做,你应该有一个线程局部的SEED变量初始化为每个线程唯一的东西。您可以使用time()
作为第一个种子,然后使用该随机序列为其他线程生成种子,或者如果您是/dev/random
或/dev/urandom
,则读取4-8个字节使用* nix。
希望能给出一些见解,因为这是午夜隆隆声,晚安&lt; 3
答案 2 :(得分:0)
为避免竞争条件,您需要为每个线程使用单独的种子变量。这意味着每个线程都有自己独立的随机数序列。