等待加入条件变量的线程会发生什么?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了等待加入条件变量的线程会发生什么?相关的知识,希望对你有一定的参考价值。
我有一个名为TThreadpool
的类,该类具有std::vector<std::thread>>
类型的成员池,并带有以下析构函数:
~TThreadpool() {
for (size_t i = 0; i < pool.size(); i++) {
assert(pool[i].joinable());
pool[i].join();
}
}
我相信,在调用析构函数时,所有线程都在一个条件变量上等待(使用永远为假的谓词控制的虚假唤醒,并且可连接的输出为true。
简化的运行线程示例为:
void my_thread() {
std::unique_lock<std::mutex> lg(mutex);
while (true) {
my_cond_variable.wait(lg, [] {
return false;
});
# do some work and possibly break, but never comes farther then wait
# so this probably should not matter
}
}
要检查正在运行的线程,我正在启动top -H
。在程序启动时,pool.size()
本身存在TThreadpool
个线程+ 1个线程。令我惊讶的是,加入这些活动线程并不会将它们从top给出的线程列表中删除。这是预期的行为吗?
((最初,我的程序有些不同-我使用qt创建了一个简单的ui应用程序,该应用程序使用在ui线程和其他受线程池控制的线程中运行的线程池,并在关闭ui窗口时调用了线程连接,但是QtCreator说我关闭窗口后我的应用程序仍然可以工作,需要我将其关闭以使其崩溃,这使我检查了线程的状态,结果发现它与qt无关。我用qt错过了一些明显的细节。
稍后,我尝试不声明可连接性,而是打印它,并发现Threadpool析构函数中的循环永远不会比第一次连接移动得更远-我没有想到并且无法解释的行为
join()
对子线程不做任何事情-直到子线程退出之前,它所做的一切都是阻塞的。它仅对调用线程有影响(即通过阻止其进度)。子线程可以保持运行所需的时间(尽管通常您希望它快速退出,这样调用join()
的线程不会长时间被阻塞-但这取决于您实现)
令我惊讶的是,加入这些活动线程并不会将它们从top给出的线程列表中删除。这是预期的行为吗?
这表明线程仍在运行。在线程上调用join()
对正在运行的线程没有任何影响。只是调用线程等待被调用线程退出。
发现Threadpool析构函数内部的循环从未比第一次连接更深入
这意味着第一个线程尚未完成。因此,其他所有线程都尚未加入(即使它们退出了)。
但是,如果线程功能正确实现,则第一个线程(以及池中的所有其他线程)应最终完成,join()
调用应该返回(假设应该退出池中的线程-但这通常不需要为true。根据应用程序,您可以简单地使线程永远运行)。
因此,似乎出现了某种死锁,或者正在等待占用一个或多个线程的某些资源。因此,您需要运行调试器。Helgrind非常有用。
您还可以尝试减少线程数(例如2),并查看问题是否可重现/明显,然后可以增加线程数。
以上是关于等待加入条件变量的线程会发生什么?的主要内容,如果未能解决你的问题,请参考以下文章