#include <random>

int f() {

    std::random_device seeder;
    std::mt19937 engine(seeder());
    std::uniform_int_distribution<int> dist(1, 6);

    return dist(engine);

}

多个线程可以安全地调用此函数吗?函数线程安全吗?
每次都调用std::random_device seeder;std::mt19937 engine(seeder());是多余的吗?

最佳答案

没有C++ std类型以非线程安全的方式使用全局数据。可以在不同的线程中访问这种类型的两个不相关实例。

默认情况下,如果没有同步,则无法从两个线程访问类型的一个实例。

您将创建局部变量。这些局部变量与其类型的任何其他实例都不相关。这里没有线程安全问题。

通过具有状态并重新使用它,可以最有效地产生伪随机值。您没有执行此操作,因此从1到6的随机数创建起来会相对昂贵。

std::random_device seeder;
std::mt19937 engine(seeder());
std::uniform_int_distribution<int> dist(1, 6);
return dist(engine);

您对std::mt19937的使用是多余的。您已经在创建一个random_device,可以将其直接输入dist,然后从中创建一个engine,然后使用engine。在这里使用engine是没有用的。

传统上,您需要从engine中创建一次mt19937(某种类型,例如seeder)。然后,您存储engine,并将其反复传递给发行版。

这一次进行了相对昂贵的“实数随机数”生成,以通过引擎通过分布生成一连串的伪随机数。

但是请注意,这种使用需要付费;您必须存储engine,并且必须防止对其进行多线程访问。

执行此操作的“正确”方法是让一个对象为您生成随机值,然后将其传递到需要的地方。存储使用的初始种子还可以使您重复执行所涉及的随机数集。

如果您不喜欢显式传递随机状态的想法,则可以使用thread_local(或带有static保护器的mutex)。
thread_local std::mt19937 engine(std::random_device{}());
std::uniform_int_distribution<int> dist(1, 6);
return dist(engine);

这将为每个线程创建一个engine,并使用engine中的值初始化random_device

关于c++ - 梅森纳捻线器对CPP安全吗,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40655814/

10-11 23:04
查看更多