Запуск и остановка группы потоков Boost
std::vector<boost::thread> threads;
for (int i = 0; i < numberOfThreads; ++i) {
boost::thread t(workerFunc);
threads.push_back(std::move(t));
}
for (auto& t : threads) {
t.join();
}
Имейте в виду, что join()
не завершает потоки, а только ожидает их завершения.
Синхронизация
Мьютексы необходимы, если несколько потоков обращаются к одним и тем же данным и по крайней мере один из них записывает данные.Вы можете использовать мьютекс, чтобы гарантировать, что несколько потоков входят в критические разделы кода.Пример:
std::queue<int> q;
std::mutex q_mu;
void workerFunc1() {
// ...
{
std::lock_guard<std::mutex> guard(q_mu);
q.push(foo);
} // lock guard goes out of scope and automatically unlocks q_mu
// ...
}
void workerFunc2() {
// ...
{
std::lock_guard<std::mutex> guard(q_mu);
foo = q.pop();
} // lock guard goes out of scope and automatically unlocks q_mu
// ...
}
Это предотвращает неопределенное поведение, такое как чтение элемента из очереди, которая не была записана полностью.Будьте осторожны - гонки данных могут привести к сбою вашей программы или повреждению ваших данных.Я часто использую такие инструменты, как Thread Sanitizer или Helgrind , чтобы убедиться, что я ничего не пропустил.Если вы хотите передать результаты только в основную программу, но вам не нужно обмениваться данными между потоками, вы можете рассмотреть возможность использования std::promise
и std::future
.