【发布时间】:2018-08-16 17:47:40
【问题描述】:
假设我有一个函数generateId 来生成随机的 64 位整数。如果我这样写generateId
uint64_t generateId() {
static thread_local std::mt19937_64 rng{std::random_device{}()};
return rng();
}
那么rng 不会在分叉后重新播种。跑步
int main() {
std::cout << generateId() << "\n";
if (fork() == 0) {
std::cout << "child: " << generateId() << "\n";
} else {
std::cout << "parent: " << generateId() << "\n";
}
return 0;
}
将为孩子和父母打印相同的数字。
有没有办法我可以写 generateId 以便它为新进程重新播种但仍然保持性能。
【问题讨论】:
-
std::random_device的另一个问题是它在 MinGW 中被破坏多年,现在仍然如此。 -
一般来说,线程、非 POD cpp 类和
fork不能很好地配合使用。 cpp 对象没有准备好在没有调用构造函数的对象上调用析构函数(或者通常按位复制它们,这是 fork 正在做的),并且fork也不能很好地与线程一起使用 - 它甚至有一部分手册页致力于它。我建议你坚持使用多线程或多进程。 -
你在第一次调用函数之前尝试过fork吗?
-
@RSahu 如果真正的程序在分叉之前需要一个随机数,一般来说并没有什么帮助。显然,虽然是的,但这是可行的
-
@rustyx 你在说什么?
fork()对所有地址空间进行按位复制(好吧,实际上是 COW,但在这种情况下并不重要),包括对象,包括那些不可轻易复制的类的对象——这通常(神奇地)有效,但我有没有看到的情况。