比起基于线程编程,更偏爱基于任务编程

如果你想异步地运行函数doAsyncWork,有两个选择。基于线程(thread-based),基于任务(task-based):

auto fut = std::async(doAsyncWork);    // "fut"的意思是"future"

在这种调用中,传递给std::async的函数对象被认为是一个任务(task)。

基于任务通常优于基于线程,在这里,doAsyncWork会返回一个值。在基于线程的调用中,没有直接的办法获取到它;而在基于任务的调用中,这很容易。如果doAsyncWork函数发出了一个异常,get函数能取到这个异常。在基于线程的方法中,如果doAsyncWork抛出了异常,程序就死亡了(std::terminate)。

一个更根本的区别是,基于任务让你摆脱线程管理的细节。

C++软件里“线程”的三种含义:

  • 硬件线程是实际执行计算的线程。现代机器体系结构为每个CPU核心提供一个或多个硬件线程。
  • 软件线程(又称为操作系统线程或系统线程)是由操作系统管理和为硬件线程进行调度的线程。软件线程创建的数量通常会比硬件线程多,因为当一个软件线程阻塞了(例如,I/O操作,等待锁或者条件变量),运行另一个非阻塞的线程能提供吞吐率。
  • std::thread是C++进程里的对象,实际上相当于它内部软件线程的句柄。一些std::thread对象表示为“null”句柄,即不持有软件线程,它要么被move过了,要么被detach了(std::thread对象和它内部软件线程的关联被切断了,即thread对象和软件线程分离了)。

软件线程是一种受限的资源,如果你想创建的线程数量多于系统提供的数量,会抛出std::system_error异常。

软件线程和硬件线程的最佳比例是取决于软件线程多久需要执行一次,而这是会动态改变的。

如果你把这些问题扔给某个人去做,你的生活就很惬意啦,然后使用std::async就能显式地做这件事:

auto fut = std::async(doAsyncWork);  // 线程管理的责任交给标准库的实现者

这个调用把线程管理的责任转交给C++标准库的实现者。例如,得到线程数超标异常的可能性显著减少,因为这个调用可能从不产生这个异常。“它是怎样做到的呢?“如果我申请多于系统提供的线程数,使用std::thread和使用std::async有区别吗?”答案是有区别,因为当用默认启动策略(default launch policy)调用std::async时,不能保证它会创建一个新的软件线程。而且,它允许调度器把指定函数(本例中的doAsyncWork)运行在请求doAsyncWork结果的线程中(例如,那个线程调用了get或者对fut使用wait ),如果系统oversubsrcibed或线程数耗尽时,合理的调度器可以利用这个优势。

使用std::async,GUI线程的响应性也是有问题的,因为调度器没有办法知道哪个线程具有严格的响应性要求。在这种情况下,你可以把std::lanuch::async启动策略传递给std::async,它那可以保证你想要运行的函数马上会在另一个线程中执行。

最先进的线程调度器使用了系统范围的线程池来避免oversubscription,而且调度器通过工作窃取(workstealing)算法来提高了硬件核心的负载均衡能力。C++标准库没有要求线程池或者工作窃取算法,而且,实话说,C++11并发技术的一些实现细节让我们很难利用到它们。但是,一些供应商会在它们的标准库实现中利用这种技术,所以我们有理由期待C++并发库会继续进步。如果你直接使用std::thread进行编程,你要承担着处理线程耗尽、oversubscription、负载均衡的压力。

有几种情况直接使用std::thread更适合,它们包括

  • 你需要使用特定平台内部线程实现的API。C++并发API通常是使用特定平台的低级API实现的,通常使用pthread或Window’s Thread。它们提供的API比C++提供的要多(例如,C++没有线程优先级的概念)。为了获取内部线程实现的API,std::thread对象有一个native_handle成员函数,而std::future(即std::async返回的类型)没有类似的东西。
  • 你需要在C++并发API之上实现线程技术。例如,实现一个C++不提供的线程池。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值