C++ 从多个线程使用 stdlib 的 rand()
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6161322/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using stdlib's rand() from multiple threads
提问by SIMEL
I have several threads which all run the same function. In each of these they generate a different random number several times. We tried to do this by putting srand(time(0))at the start of the function, but it seems that they all get the same number.
我有几个线程都运行相同的功能。在每一个中,它们都会多次生成不同的随机数。我们试图通过srand(time(0))在函数的开头放置来做到这一点,但似乎它们都得到了相同的数字。
Do we need to call srand(time(0))only once per program, i.e at the start of main(for example), at the start of each function that is called several times, or something else?
我们是否需要srand(time(0))每个程序只调用一次,即在main(例如)开始时,在每个被调用多次的函数开始时,或者其他什么?
采纳答案by Frédéric Hamidi
srand()seeds the random number generator. You should only have to call srand(time(NULL))once during startup.
srand()为随机数生成器提供种子。您应该只需要srand(time(NULL))在启动期间调用一次。
That said, the documentation states:
也就是说,文档指出:
The function
rand()is not reentrant or thread-safe, since it uses hidden state that is modified on each call. This might just be the seed value to be used by the next call, or it might be something more elaborate. In order to get reproducible behaviour in a threaded application, this state must be made explicit. The functionrand_r()is supplied with a pointer to anunsigned int, to be used as state. This is a very small amount of state, so this function will be a weak pseudo-random generator. Trydrand48_r(3) instead.
该功能
rand()是不可重入或线程安全的,因为它使用的是在每个调用修改隐藏状态。这可能只是下一次调用要使用的种子值,或者可能更复杂。为了在线程应用程序中获得可重现的行为,必须明确表示此状态。该函数rand_r()提供了一个指向unsigned int, 用作状态的指针。这是一个非常少量的状态,所以这个函数将是一个弱伪随机生成器。drand48_r改为尝试 (3)。
The emphasized part of the above is probably the reason why all your threads get the same number.
上面强调的部分可能是您所有线程获得相同数字的原因。
回答by Peter Heath
If you are launching the threads all at the same time, the time sent to srand is probably the same for each thread. Since they all have the same seed, they all return the same sequence. Try using something else like a memory address from a local variable.
如果您同时启动所有线程,则每个线程发送到 srand 的时间可能相同。由于它们都具有相同的种子,因此它们都返回相同的序列。尝试使用其他东西,例如来自局部变量的内存地址。
回答by kshepherd
As you are using C++, rather than C, you may be able to avoid the threading problems often associated with srand/rand by using c++11. This depends on using a recent compiler which supports these features. You would use a separate engine and distribution on each thread. The example acts like a dice.
由于您使用的是 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.
I referred to Wikipedia C++11and Boost randomwhen answering this question.
我在回答这个问题时参考了维基百科 C++11和Boost random。
回答by Mat
From the randman page:
从rand手册页:
The function rand() is not reentrant or thread-safe, since it uses hidden state that is modified on each call.
函数 rand() 不是可重入的或线程安全的,因为它使用在每次调用时修改的隐藏状态。
So don't use it with threaded code. Use rand_r(or drand48_rif you're on linux/glibc). Seed each RNG with a different value (you could seed a first RNG in the main thread to produce random seeds for the ones in each thread).
所以不要将它与线程代码一起使用。使用rand_r(或者drand48_r如果您使用的是 linux/glibc)。用不同的值为每个 RNG 设置种子(您可以在主线程中设置第一个 RNG 以生成每个线程中的随机种子)。
回答by jcoder
That's a good question. I can't directly answer it because I think there are bigger issues. It doesn't even seem to be clear that rand is thread safe at all anyway. It maintains internals state and it doesn't seem to be well defined if that's per process or per thread, and if it's per process if it's thread safe.
这是个好问题。我无法直接回答,因为我认为还有更大的问题。无论如何,rand 是否是线程安全的似乎都不清楚。它维护内部状态,如果它是每个进程或每个线程,它似乎没有很好地定义,如果它是线程安全的,它是否是每个进程。
To be sure I would lock a mutex around each access.
为了确保我会在每次访问周围锁定一个互斥锁。
Or preferably use a better defined generate such as one from boost
或者最好使用更好定义的生成,例如来自boost 的生成
回答by Michael Entin
C was not designed for multithreading, so behavior of srand() with multithreading is not defined and depends on the C runtime library.
C 不是为多线程设计的,所以 srand() 多线程的行为没有定义,取决于 C 运行时库。
Many Unix/Linux C runtime libraries use single static state, which is not safe to access from multiple threads, so with these C runtimes you can't use srand() and rand() from multiple threads at all. Other Unix C runtimes may behave differently.
许多 Unix/Linux C 运行时库使用单个静态状态,从多个线程访问这是不安全的,因此对于这些 C 运行时,您根本无法从多个线程使用 srand() 和 rand()。其他 Unix C 运行时的行为可能有所不同。
Visual C++ runtime uses per-thread internal state, so it is safe to call srand() for each thread. But as Neil pointed out, you will likely seed all threads with same value - so seed with (time + thread-id) instead.
Visual C++ 运行时使用每个线程的内部状态,因此为每个线程调用 srand() 是安全的。但正如 Neil 指出的那样,您可能会用相同的值为所有线程设置种子 - 所以用 (time + thread-id) 代替。
Of course, for portability, use Random objects rather than rand function, and then you would not depend on hidden state at all. You still need one object per thread, and seeding each object with (time + thread-id) is still a good idea.
当然,为了可移植性,使用 Random 对象而不是 rand 函数,这样你就完全不依赖隐藏状态了。每个线程仍然需要一个对象,并且用 (time + thread-id) 为每个对象播种仍然是一个好主意。

