[英]Safe random number generation using rand() or std::random_device in C++
我很難找到有關 C++ 中隨機數生成的線程安全性的令人信服的來源。
我正在開發的應用程序目前很少有線程訪問隨機數生成,但將來可能會有更多線程。
使用的第一件事是:
int randomInRange(const int min, const int max)
{
srand(time(0));
return min + (rand() % max);
}
我發現這是錯誤的,因為種子是為每次調用設置的,它會對rand()
函數的統計隨機性和性能產生負面影響。
接下來嘗試的是使用一個單例,它包含一個std::mt19937
實例:
// RandomHelper.h
class RandomHelper
{
private:
std::mt19937 engine;
// Singleton
RandomHelper() : engine(std::random_device()()) {}
public:
static RandomHelper& getInstance();
int randomInRange(int min, int max)
{
std::uniform_int_distribution<int> uidist(min, max);
return uidist(engine);
}
};
// RandomHelper.cpp
RandomHelper& RandomHelper::getInstance()
{
static RandomHelper instance;
return instance;
}
這應該有助於統計隨機性。 但是為此,我知道每個線程都有一個std::mt19937
實例會更好。
我不確定我明白為什么。
這是因為如果多個線程同時調用RandomHelper::getInstance().randomInRange(.., ..)
他們會得到相同的結果嗎? 又名它不是線程安全的?
為了避免這種可能性,現在實施如下:
int randomInRange(const int min, const int max)
{
thread_local std::mt19937 engine(std::random_device{}());
std::uniform_int_distribution<int> uidist(min, max);
return uidist(engine);
}
到目前為止,這看起來是最好的解決方案,但我找不到關於std::mt19937
或std::random_device
線程安全性的太多信息,以查看是否確實需要擁有這些與單個實例的 thread_local 變體單身人士。
我願意做更多的研究,但除了通常的 C++ 參考文獻之外,我不知道在哪里查看,據我所知,這些參考文獻沒有提到任何關於線程安全的內容。
隨機數生成器引擎不是線程安全的。
使用thread_local
為每個線程初始化一個引擎使其線程安全,所以我會說你的解決方案很好。
如果您對random_device
的線程安全性有疑問,也可以將其thread_local
:
int randomInRange(const int min, const int max)
{
thread_local std::random_device rd;
thread_local std::mt19937 rng(rd());
thread_local std::uniform_int_distribution<int> uid;
return uid(rng, decltype(uid)::param_type{min,max});
}
有更多的線程談論這個沒有提到:
我敢肯定還有更多。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.