The appropriate default for seeding is:
std::random_device r;
std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
std::mt19937 eng(seed);
You could simply do this on each thread and it should work:
#include <algorithm>
#include <functional>
#include <iostream>
#include <iterator>
#include <mutex>
#include <random>
#include <thread>
int main() {
std::mutex iomutex;
std::vector<std::thread> threads;
for (int i = 0 ; i < 10; ++i) {
threads.emplace_back([&iomutex](int tid) {
std::random_device r;
std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
std::mt19937 eng(seed);
std::uniform_int_distribution<> dist(1, 100);
std::lock_guard<std::mutex> ioguard(iomutex);
std::cout << "Thread " << tid << ": ";
std::generate_n(std::ostream_iterator<int>(std::cout, " "), 10, std::bind(dist, eng));
std::cout << '\n';
}, i);
}
for (auto &&t : threads) {
t.join();
}
}
Alternatively you could compute the seeds on the main thread and pass each worker the data to initialize its engine. Unfortunately you can't pass a seed_seq
, so in the example below I simply pass an initialized engine.
int main() {
std::mutex iomutex;
std::vector<std::thread> threads;
std::random_device r;
for (int i = 0 ; i < 10; ++i) {
std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
std::mt19937 thread_eng(seed);
threads.emplace_back([&iomutex](int tid, std::mt19937 init_eng) {
std::mt19937 eng(std::move(init_eng));
std::uniform_int_distribution<> dist(1, 100);
std::lock_guard<std::mutex> ioguard(iomutex);
std::cout << "Thread " << tid << ": ";
std::generate_n(std::ostream_iterator<int>(std::cout, " "), 10, std::bind(dist, eng));
std::cout << '\n';
}, i, thread_eng);
}
for (auto &&t : threads) {
t.join();
}
}