我正在尝试使用 boost::async
和 boost::future
来自“Boost.Thread”(Boost 1.71.0)作为 std::async
的线程池就绪替代品和 std::future
使用 Mingw (g++ 9.2.0)。这太好了,因为 std::async
有明显的缺点(例如,参见此处的评论:Is it better to use the default launch policy for std::async with newer compilers?)。
我正在使用 async
执行任务的代码自己发起任务。与 std::async
这很有效。但是现在使用 boost::async
时和一个线程池,我的应用程序卡住了。 CPU 负载降为零,但应用程序没有继续。
这个例子演示了这个问题:
#define BOOST_THREAD_VERSION 5
#define BOOST_NO_SFINAE_EXPR
#include <boost/thread.hpp>
#include <boost/thread/executors/basic_thread_pool.hpp>
#include <iostream>
#include <vector>
int main()
{
// Use three threads. As soon as the thread number is raised enough,
// the problem will be gone.
boost::basic_thread_pool threadPool(3);
std::vector<boost::future<void>> futures;
for (int index = 0; index < 3; ++index)
{
futures.push_back(boost::async(threadPool, [&threadPool]()
{
for (int anotherIndex = 0; anotherIndex < 3; ++anotherIndex)
{
boost::future<void> future = boost::async(threadPool, []()
{
std::cout << "1" << std::endl;
}
);
future.get();
}
}));
}
for (auto& future : futures)
{
future.get();
}
std::cout << "Done." << std::endl;
return 0;
}
现在如果我增加线程池中的线程数(例如增加到十个),问题就会消失。该应用程序将成功完成。这使我得出这样的解释:“外部”任务使用线程池中的可用线程。然后他们开始更多的任务并等待他们。但是如果线程数限制太多,它们的子任务将无法运行,因为线程被父线程阻塞了。因此, parent 永远等待。
这个解释正确吗?为什么会这样?如果之前没有使用过线程池。这对线程池来说很常见吗?或者它是“Boost.Thread”的错误实现(相应的代码仍然是实验性的!)。为什么不 boost::future<>::get()
暂时释放自己的线程,如果任务还没有完成,让其他任务同时使用cpu?是否有针对该阻塞的解决方案?该解决方案是解决方法还是常用模式?
最佳答案
future.get();
这会阻塞运行当前任务的 worker。由于它等待另一个任务,除非池中有空闲工作人员来运行该任务,否则它永远不会进行。
具体的任务分配是不明确的(这里我觉得要看平台调度和实现),很容易看出你已经发了3个外层任务(饱和池),内层任务很容易遇到这样的情况所有工作人员都被阻止执行一项内部任务。
关于c++ - 为什么在使用线程池时对 boost::async 的嵌套调用会阻塞?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57987570/