为什么我应该使用std :: async?

我试图深入探索新的C ++ 11标准的所有选项,同时使用std :: async并阅读其定义,我注意到了两件事情,至少在linux下使用gcc 4.8.1:

  • 它被称为异步,但它有一个真正的“顺序行为”,基本上在你调用将与异步函数foo关联的未来的行中,程序将阻塞,直到foo执行完成。
  • 它依赖于与其他外部库完全相同的外部库,以及更好的非阻塞解决方案,这意味着pthread ,如果要使用std::async ,则需要pthread。
  • 在这一点上,我很自然地问为什么选择std :: async而不是一组简单的函子呢? 这个解决方案甚至根本无法扩展规模,您呼叫的未来越多,程序响应也就越少。

    我错过了什么吗? 你能否展示一个被授予以异步,非阻塞方式执行的示例?


    如果您需要异步操作的结果,那么无论您使用哪个库,都必须阻止。 这个想法是,你可以选择什么时候阻止,并且希望当你这样做的时候,你阻止了一个微不足道的时间,因为所有的工作已经完成了。

    还要注意std::async可以用政策推出std::launch::asyncstd::launch::deferred 。 如果您没有指定它,则可以选择实现,并且可以选择使用延迟评估,这会在您尝试从未来获得结果时导致所有工作都已完成,从而导致较长的块。 所以如果你想确保工作是异步完成的,可以使用std::launch::async


  • 它被称为异步,但它有一个真正的“顺序行为”,
  • 不,如果你使用std::launch::async策略,它会在一个新线程中异步运行。 如果您未指定可能在新线程中运行的策略。

    基本上在你调用将与异步函数foo关联的将来的行中,程序将阻塞,直到foo执行完成。

    它只会在foo没有完成时阻塞,但如果它是异步运行的(例如,因为您使用std::launch::async策略),它可能在您需要之前完成。

  • 它依赖于与其他外部库完全相同的外部库,以及更好的非阻塞解决方案,这意味着pthread,如果要使用std :: async,则需要pthread。
  • 错误的是,它不必使用Pthreads来实现(在Windows上它不是,它使用ConcRT功能)。

    在这一点上,我很自然地问为什么选择std :: async而不是一组简单的函子呢?

    因为它保证了线程安全并跨线程传播异常。 你能用一套简单的仿函数来做到吗?

    这个解决方案甚至根本无法扩展规模,您呼叫的未来越多,程序响应也就越少。

    不必要。 如果您没有指定启动策略,那么智能实现可以决定是否启动新线程,或返回延迟函数,或返回稍后决定的事情,以便有更多资源可用时。

    现在的确,在GCC的实现中,如果你没有提供启动策略,那么对于当前版本,它将永远不会运行在一个新线程中(这里有一个bugzilla报告),但这是该实现的属性,而不是std::async一般的std::async 。 您不应该将标准中的规范与特定的实现混淆。 阅读一个标准库的实现是学习C ++ 11的一个不好的方法。

    你能否展示一个被授予以异步,非阻塞方式执行的示例?

    这不应该阻止:

    auto fut = std::async(std::launch::async, doSomethingThatTakesTenSeconds);
    auto result1 = doSomethingThatTakesTwentySeconds();
    auto result2 = fut.get();
    

    通过指定启动策略,您可以强制执行异步执行,并且如果您在执行其他任务时执行了其他任务,那么当您需要时,结果将会准备就绪。


    我认为你的问题是std::future说它会阻止get 。 只有在结果尚未准备好的情况下,它才会阻止。

    如果您可以安排结果已经准备就绪,这不是问题。

    有很多方法可以知道结果已经准备好。 您可以轮询future并询问它(相对简单),您可以使用锁定或原子数据来传达它已准备好的事实,您可以构建一个框架以将“已完成”的future项目交付到消费者可以与之交互的队列中,你可以使用某种类型的信号(它只是一次阻止多个事物,或轮询)。

    或者,您可以完成您可以在本地完成的所有工作,然后阻止远程工作。

    作为一个例子,设想一个并行递归合并排序。 它将数组拆分为两个块,然后对一个块进行async排序,同时对另一个块进行排序。 一旦完成对其一半的排序,直到第二个任务完成后,始发线程才能进行。 所以它做了一个.get()和块。 一旦完成了两部分的排序,就可以进行合并(理论上,合并至少可以部分并行完成)。

    这个任务对于那些在外部进行交互的人来说就像是一个线性任务 - 完成后,数组将被排序。

    然后我们可以将它包装在一个std::async任务中,并且有future排序数组。 如果我们想要的话,我们可以添加一个信号程序让我们知道future已经完成,但只有当我们有一个线程等待信号时才有意义。

    链接地址: http://www.djcxy.com/p/30729.html

    上一篇: Why should I use std::async?

    下一篇: Are the days of passing const std::string & as a parameter over?