[c++11] std::async std::packaged_task std::promise and std::future notes

把std::async,std::packaged_task,std::promise三个放在一起来说,是因为他们都可以返回一个std::future对象.简单来说,当某个线程需要等待一个特定的一次性事件(one-off event),它可以用一个”future”来表示这个事件.

std::async

有的时候可能你需要做一个花费事件比较长的计算,但是计算结果不是立刻需要.这个时候就可以用一个新的线程来做这个计算.这里比较关键的问题是如何将在新线程进行计算的结果传回到当前线程,因为std::thread并没有提供一个类似的机制.

这个时候就需要std::async登场了.

当然也可以与向std::thread包装的thread function中传参数一样,向std::async中传参数,如下:

此外,std:;async还有一个可选参数,值为std::launch::deferred或std::launch:async或std::launch::deferred|std::launch:async,第三种为默认参数.

std::launch::async表示该task会立即在一个新的thread上执行.

std::launch::deferred 表示该task不会被立刻执行,而是在调用get()或者wait()的时候才会执行.这里需要注意的是,调用get()或者wait()的线程,可以是和调用async()属于同一个线程,也可以属于不同线程.

笼统来说,std::launch:deferred是一种更为灵活的方式.具体请参考cppreference_async

std::packaged_task

std::packaged_task有点类似std::function,将要在其他线程执行的对象封装了起来。

与std::async相比,std::packaged_task不会直接执行任务,而是需要显示调用,因此可以做到将执行函数的时机和获取future的时机分离

std::promise

第一次用c++11写多线程就是用的promisepromise && future leanrning notes

个人认为std::promise与std::async或者std:;packaged_task最明显的区别是,它的值不是一个函数的返回值,而是可以通过set_value来设置,因此更加灵活。

需要注意的是,std::promise不支持拷贝构造,因此需要使用std::move或者传promise的指针。

 

In summary

  • async:提供最高层次的抽象。如果你不需要控制线程的运行时机,就选这个。
  • packaged_task:抽象层次比 async低。如果你需要控制线程的运行时机,且线程执行的结果即目标结果时,选这个。
  • promise:抽象层次最低。当你想在线程中设置目标结果的值,选这个。

 

参考资料:

货比三家:C++ 中的 task based 并发

What is the difference between packaged_task and async

std::promise

 

作者: CrazyKK

ex-ACMer@hust,stackoverflow-engineer@sensetime

说点什么

您将是第一位评论人!

提醒
wpDiscuz