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

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

  • 它被称为asynchronous ,但它有一个真正的“顺序行为”,基本上在你调用与你的asynchronous函数foo相关联的未来的行中,程序阻塞直到foo执行完成。
  • 它依赖于与其他外部库完全相同的外部库,以及更好的非阻塞解决scheme,这意味着pthread ,如果要使用std::async ,则需要pthread。

在这一点上,我很自然的问为什么selectstd :: async而不是一组简单的函子呢? 这个解决scheme甚至根本就没有规模,你呼叫的未来越多,程序响应也就越less。

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

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

还要注意, std::asyncstd::launch::deferred可以启动std::launch::async 。 如果不指定它,则允许select实现,并且可以select使用延迟评估,这会导致在您尝试从未来获得结果时完成所有工作,从而导致较长的块。 所以如果你想确保工作是asynchronous完成的,使用std::launch::async

  • 它被称为asynchronous,但它有一个真正的“顺序行为”,

不,如果你使用std::launch::async策略,那么它会在一个新的线程中asynchronous运行。 如果您不指定可能在新线程中运行的策略。

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

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

  • 它依赖于与其他外部库完全相同的外部库,以及更好的非阻塞解决scheme,这意味着pthread,如果要使用std :: async,则需要pthread。

错误的是,它不必使用Pthreads来实现(在Windows上它不是,它使用ConcRTfunction)。

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

因为它保证了线程安全并在线程之间传播exception。 你可以做一个简单的仿函数?

这个解决scheme甚至根本就没有规模,你呼叫的未来越多,程序响应也就越less。

不必要。 如果你没有指定启动策略,那么聪明的实现可以决定是否启动一个新的线程,或者返回一个延迟的函数,或者当更多的资源可用时返回稍后决定的内容。

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

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

这不应该阻止:

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

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

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

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

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

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

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

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

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

在参考中 : http : //en.cppreference.com/w/cpp/thread/async

如果设置了asynchronous标志(即policy&std :: launch :: async!= 0),那么asynchronous在独立的执行线程上执行函数f,就好像由std :: thread(f,args …) ,除了如果函数f返回一个值或抛出一个exception,它将被存储在通过std :: future访问的共享状态中,asynchronous返回给调用者

logging抛出的exception是一个不错的属性。