Item35:优先考虑基于任务的编程而非基于线程的编程

程序员小x大约 2 分钟C++effective modern c++读书笔记

Item35:优先考虑基于任务的编程而非基于线程的编程

通常我们想执行一个异步任务的时候,通常会采用线程的方法。本节介绍了一种新的方法,即std::async。其和std::thread有很大的相似性。

std::async的一个调用的例子如下所示:

auto fut = std::async(doAsyncWork); //"fut"表示"future"

从调用的形式可以看出,std::async会返回一个std::future对象,这将让我们很方便的线程获取返回值。

因为线程存在处理线程耗尽、资源超额、负责均衡问题,如果我们使用std::thread,就需要自己处理上述问题。但是std::async则会帮助我们处理这些问题。

上述便是两点std::async的优势。本节是建议大家在解决问题时,可以优先考虑std::async,因为其简单易用。 但是这不意味着不使用std::thread

在下面的场景中,std::thread更具有优势:

  • 你需要访问非常基础的线程API。C++并发API通常是通过操作系统提供的系统级API(pthreads或者Windows threads)来实现的,系统级API通常会提供更加灵活的操作方式(举个例子,C++没有线程优先级和亲和性的概念)。为了提供对底层系统级线程API的访问,std::thread对象提供了native_handle的成员函数,而std::future(即std::async返回的东西)没有这种能力。
  • 你需要且能够优化应用的线程使用。举个例子,你要开发一款已知执行概况的服务器软件,部署在有固定硬件特性的机器上,作为唯一的关键进程。
  • 你需要实现C++并发API之外的线程技术,比如,C++实现中未支持的平台的线程池。

总结

  • std::thread API不能直接访问异步执行的结果,如果执行函数有异常抛出,代码会终止执行。
  • 基于线程的编程方式需要手动的线程耗尽、资源超额、负责均衡、平台适配性管理。
  • 通过带有默认启动策略的std::async进行基于任务的编程方式会解决大部分问题。
Loading...