我正在尝试使用可用的ThreadPool
类here
不幸的是,此类的设计方式是在创建时创建其线程并将它们加入析构函数中。为了使其更灵活并能够在其中多次创建线程,我向此类添加了以下函数:
void join_all() {
condition.notify_all();
for (std::thread &worker : workers) {
worker.join(); // I get blocked here
}
}
但是,通过此更改,在运行以下主程序时:
int main() {
ThreadPool pool(4);
for (int i = 0; i < 8; ++i) {
pool.enqueue([i]() {
std::cout << "HELLO " << i << std::endl;
});
}
pool.join_all(); // here I am blocked
return 0;
}
尝试加入第一个线程时,我的主线程将在join_all
函数内被阻止。
编写join_all()
函数的正确方法是什么,它可以让我继续使用池而不终止它?
ThreadPool
类已经在其析构函数上加入了线程。但是,如果您想拥有自己的join_all()
函数(出于任何原因),也应该设置stop
变量:
void join_all()
{
{
std::unique_lock<std::mutex> lock(queue_mutex);
stop = true;
}
condition.notify_all();
for (std::thread &worker : workers) {
worker.join();
}
}
警告:现在,您应该在线程上进行两次联接时要小心。因此,我建议在连接之前检查线程(例如在析构函数中):
for (std::thread &worker : workers)
{
if (worker.joinable())
{
worker.join();
}
}
通过这些更改,代码可以在没有无限循环的情况下工作。