mat*_*ort 34
这不是一个或两件事 - 你可以使用手工创建的std :: threads进行期货(连同promises).使用std::async
是一种方便的方法来触发一个线程进行一些异步计算,并通过未来封送结果,但std::async
在当前标准中相当有限.如果接受来自Microsoft PPL的一些想法的建议扩展,它将变得更有用.
目前,std::async
对于相当简单的程序来说,最适合处理非常长时间运行的计算或长时间运行的IO.它并不能保证低开销(实际上它的指定方式使得在后台使用线程池很难实现),因此它不适合更细粒度的工作负载.为此,您需要使用std::thread
或使用Microsoft的PPL或Intel的TBB等自己的线程池.
您还可以使用std::thread
以更现代和可移植的方式编写的"传统"POSIX线程样式代码.
Bartosz Milewski讨论了std::async
目前在他的文章" C++ 11中的异步任务:不是很有趣"中指出的方法的一些局限性
小智 6
使用std::futrue
over 的一个用例std::thread
是您想要调用一个返回值的函数。当你想要函数的返回值时,你可以调用get()
未来的方法。
std::thread
不提供获取函数返回值的直接方法。
我意识到这个问题提出已经有8年了。从那时起,C++ 并发环境发生了很大变化。最近我也不得不在这片风景中徘徊,不知道该走哪条路继续前进。我想分享一些我的想法,并可能得到验证。我会将原来的问题稍微修改为 std::async vs 线程池,而不仅仅是 std::thread 。
自 2011 年以来,我一直大量使用 boost::thread_group 和 boost::asio::io_service 分别进行线程池和事件循环。我的每个应用程序都是这样开始的:
int noOfCores = boost::thread::hardware_concurrency();
for (int i = 0; i < noOfCores; i++)
{
_threadPool.create_thread(boost::bind(&pri_queue::run, &_taskQueue));
}
Run Code Online (Sandbox Code Playgroud)
任务队列 _taskQueue 的类型是 pri_queue ,与此boost 示例有些相似,除了我的 run() 函数等待 io_service.run_one() 。因此,我还通过在排队时分配优先级来控制任务执行的优先级。
之后,我可以使用 post() 在该队列中抛出任何函数(使用 boost::bind 与参数绑定)来执行,或者使用 boost::asio::deadline_timer::async_wait() 延迟调度它。
由于我的框架中的所有内容都是事件驱动的,因此我很乐意将任何功能划分为多个函数对象,同时等待事件,就像异步 http 客户端的 boost 示例一样。该模型经过了时间的考验,没有线程创建成本,因为每个线程都是预先创建的。
然而,自从我在公司的所有产品中采用这种模型以来,C++ 标准已经更新了 3 次(14、17、20)。所以你可以说,当我看到周围出现的所有新变化时,我有点害怕害怕错过。请原谅,在查看了 std::async 和协程之后,我不明白它们如何帮助像我这样已经习惯使用 io_service + 线程池模型的人。它看起来更昂贵,而且我无法控制优先级或线程创建,不同编译器的实现有所不同。
我发现,与分散到多个函数对象中的异步功能相比,它使函数显得同步且结构化(所有部分都集中在一个地方)。
对于 C++ 老手来说,我认为线程池比 std::async 甚至协程更好。当然,如果应用程序不是事件驱动的,或者如果您不熟悉异步编程,则 std::async 会更容易处理。
我发现的一个简单原因就是当你想要一种方法来检测(通过轮询)异步作业是否完成时.有了std::thread
,你必须自己管理它.随着std::async
您可以查询std::future::valid()
(或使用std::future::wait_for/wait_until(...)
),当它完成就知道了.
归档时间: |
|
查看次数: |
33245 次 |
最近记录: |