【Effective Modern C++】第七章 并发API:35. 优先考虑基于任务的编程而非基于线程的编程

两种异步执行方式的直观对比

基于线程(thread-based):直接创建 std::thread
c++ 复制代码
int doAsyncWork();
std::thread t(doAsyncWork); // 直接创建线程执行函数
  • 无直接获取返回值的方式;
  • 若函数抛出异常,程序会直接调用std::terminate终止。
基于任务(task-based):使用 std::async
c++ 复制代码
auto fut = std::async(doAsyncWork); // 提交任务,返回future对象
  • 代码更简洁;
  • futureget()函数可获取返回值,还能捕获函数抛出的异常(避免程序终止);
  • 线程管理的责任交给标准库,而非开发者。

理解线程的三层含义

线程类型 定义
硬件线程 CPU 核心提供的真实执行单元,是计算的物理载体。
软件线程(OS 线程) 操作系统管理的线程,运行在硬件线程上,数量可多于硬件线程(阻塞时 OS 调度其他线程)。
std::thread C++ 中 "软件线程" 的句柄,可能为空(默认构造、移动、join、detach 后无对应软件线程)。

基于线程编程的痛点

直接使用std::thread的核心问题在于需要开发者手动处理线程管理的复杂问题:

  • 线程资源有限 :系统支持的软件线程数量有上限,创建超出限额的std::thread会抛出std::system_error异常;即使函数本身noexcept,也可能触发此异常,且异常处理逻辑复杂(比如回退到当前线程执行会导致负载不均、GUI 线程响应慢)。

  • 资源超额(oversubscription) :可运行的软件线程数 > 硬件线程数时,OS 会对线程做时间切片,引发上下文切换

    • 上下文切换本身增加系统开销;
    • 若线程切换到不同硬件核心,会导致 CPU 缓存失效(无可用数据 / 指令),还会 "污染" 原核心的缓存,进一步降低性能。
  • 优化难度极高:软件线程与硬件线程的最佳比例是动态变化的(比如程序从 IO 密集型变为计算密集型),且依赖硬件特性(缓存大小、核心数),跨平台适配几乎不可能。

基于任务编程的优势

std::async的价值是将线程管理的责任交给标准库,规避上述痛点:

  • 灵活的调度策略 :默认启动策略下,std::async不保证创建新线程;当系统线程耗尽 / 资源超额时,会将任务调度到 "等待结果的线程"(调用fut.get()/fut.wait()的线程)上执行,避免线程创建失败或资源超额。
  • 更智能的运行时调度 :标准库调度器(部分实现采用线程池 + 工作窃取算法)比开发者更了解系统全局状态(所有执行过程),能更好地实现负载均衡,优化上下文切换和缓存利用。
  • 天然支持结果 / 异常处理futureget()函数可获取异步执行的返回值,或捕获函数抛出的异常,避免程序终止。

仍需使用 std::thread 的特殊场景

  • 需要访问底层线程 API:std::thread提供native_handle()成员函数,可操作线程优先级、亲和性等(std::future无此能力);
  • 可精准优化线程使用:比如部署在固定硬件上、执行概况明确的服务器(作为唯一关键进程);
  • 实现标准库不支持的线程技术:比如特定平台未被 C++ 标准库实现的线程池。

总结

  1. 基于线程的编程(std::thread)需要手动处理线程耗尽、资源超额、负载均衡等复杂问题,且无法直接获取异步执行结果,函数异常会导致程序终止;
  2. 基于任务的编程(std::async)将线程管理交给标准库,默认启动策略可规避大部分线程管理痛点,还能通过 future 获取结果 / 捕获异常;
  3. 仅在需要访问底层线程 API、精准优化线程使用或实现非标线程技术时,才考虑直接使用 std::thread。

原著在线阅读地址

相关推荐
hansang_IR2 小时前
【记录】AT_abc406模拟赛
c++·算法·模拟赛
消失的旧时光-19433 小时前
C++ 多线程与并发系统取向(七)—— 并发排障与工程纪律(从“会写”到“能控场”)
开发语言·c++·并发
小老鼠不吃猫4 小时前
深入浅出(十三)QWT库——高稳定二维绘图
c++·qt·二维图
无忧.芙桃4 小时前
AVL树的实现
数据结构·c++
遥望九龙湖4 小时前
打包动态库
开发语言·c++·visualstudio
tankeven4 小时前
HJ101 排序
c++·算法
不想看见4044 小时前
01 Matrix 基本动态规划:二维--力扣101算法题解笔记
c++·算法·leetcode
麻瓜pro5 小时前
【迭代】高性能c++实时对话系统e2e_voice
开发语言·c++·onnxruntime·端到端语音
特种加菲猫5 小时前
深入理解string:通过模拟实现探讨其内部机制
c++