簡體   English   中英

在 C++ 中使用 rand() 或 std::random_device 生成安全隨機數

[英]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::mt19937std::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});
}

有更多的線程談論這個沒有提到:

C++線程安全均勻分布隨機數生成

C++11 隨機數生成器的線程安全

我敢肯定還有更多。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM