news 2026/4/26 14:57:15

C++11 异步编程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++11 异步编程

std::async+std::future:最简单的异步任务

1. 作用

  • std::async启动异步任务(可选择 “开新线程” 或 “延迟执行”),并返回std::future接收结果;
  • std::future独占式结果容器—— 存储异步任务的结果,结果只能被获取一次。

2.std::async核心函数

// 形式1:指定启动策略 template <class Fn, class... Args> std::future<typename std::result_of<Fn(Args...)>::type> async(std::launch policy, Fn&& fn, Args&&... args); // 形式2:默认策略(编译器自动选择) template <class Fn, class... Args> std::future<typename std::result_of<Fn(Args...)>::type> async(Fn&& fn, Args&&... args);
  • 参数说明:
    • policy:启动策略(控制任务执行方式):
      • std::launch::async:强制立刻开新线程执行任务;
      • std::launch::deferred:延迟执行(直到调用future::get()时,在当前线程执行);
    • fn:异步任务(函数、lambda、函数对象等);
    • Args...:任务fn的参数;
  • 返回值:std::future<T>Tfn的返回类型),用于接收任务结果。

3.std::future核心成员函数

std::future独占式结果容器(一个future只能对应一个异步结果),因此它的拷贝构造函数和拷贝赋值运算符被显式删除,只能通过移动语义转移所有权(用std::move)。

函数作用
T get()阻塞当前线程,等待任务完成并返回结果;⚠️ 注意:只能调用一次,调用后future失效。
void wait()阻塞线程直到任务完成,但不获取结果
future_status wait_for(const chrono::duration<Rep, Period>& rel_time)等待指定时长,返回任务状态:-ready:任务完成;-timeout:超时未完成;-deferred:任务延迟执行。

4. 样例:用async+future后台计算

#include <iostream> #include <future> #include <chrono> using namespace std; // 异步任务:计算a+b int add(int a, int b) { this_thread::sleep_for(chrono::seconds(2)); // 模拟耗时 return a + b; } int main() { // 1. 启动异步任务(显式指定async策略,开新线程) future<int> fut = async(launch::async, add, 3, 5); // 2. 主线程做其他事 cout << "主线程:等待后台计算..." << endl; // 3. 等待任务状态(最多等1秒) future_status status = fut.wait_for(chrono::seconds(1)); if (status == future_status::timeout) { cout << "主线程:等待超时,任务还在运行..." << endl; } // 4. 获取结果(阻塞直到任务完成) int result = fut.get(); cout << "主线程:计算结果是 " << result << endl; // 输出8 return 0; }

二、std::promise:主动向线程外传递结果

1. 作用

std::promise主动承诺结果的工具:一个线程通过promise主动设置结果,另一个线程通过绑定的future获取结果(适合 “线程内主动传结果” 的场景)。

2.std::promise核心成员函数

函数作用
future<T> get_future()获取与当前promise绑定的future;⚠️ 注意:一个promise只能调用一次。
void set_value(const T& val)设置任务结果(“兑现承诺”);⚠️ 注意:只能调用一次,否则崩溃。
void set_exception(exception_ptr e)设置异常结果 —— 其他线程调用future::get()时会抛出该异常。

3. 样例:用promise主动传结果

#include <iostream> #include <future> #include <thread> #include <chrono> using namespace std; // 线程函数:用promise设置结果 void calc(promise<int>& prom) { this_thread::sleep_for(chrono::seconds(2)); // 模拟计算 int res = 10 * 5; prom.set_value(res); // 主动设置结果 } int main() { // 1. 创建promise promise<int> prom; // 2. 获取绑定的future future<int> fut = prom.get_future(); // 3. 启动线程,传递promise(必须用ref传引用) thread t(calc, ref(prom)); // 4. 主线程获取结果 cout << "主线程:等待线程传结果..." << endl; int result = fut.get(); cout << "主线程:线程计算结果是 " << result << endl; // 输出50 t.join(); return 0; }

三、std::packaged_task:包装任务的容器

1. 作用

std::packaged_task任务包装器:将 “函数、lambda” 等可调用对象包装成 “异步任务”,同时绑定future—— 执行包装的任务后,结果会存入future(适合 “封装任务到线程池 / 队列” 的场景)。

2.std::packaged_task核心成员函数

函数作用
explicit packaged_task(Fn&& fn)构造函数:用可调用对象fn初始化任务。
future<T> get_future()获取与包装任务绑定的future;⚠️ 注意:一个packaged_task只能调用一次。
void operator()(Args&&... args)执行包装的任务,args是任务参数;执行后结果存入对应的future

3. 样例:用packaged_task包装阶乘任务

#include <iostream> #include <future> #include <thread> using namespace std; // 要包装的任务:计算n的阶乘 int factorial(int n) { int res = 1; for (int i = 1; i <= n; ++i) res *= i; return res; } int main() { // 1. 包装任务(把factorial包装成packaged_task) packaged_task<int(int)> task(factorial); // 2. 获取绑定的future future<int> fut = task.get_future(); // 3. 启动线程执行任务(必须用move转移任务所有权) thread t(move(task), 5); // 计算5的阶乘 // 4. 获取结果 cout << "等待阶乘计算..." << endl; int result = fut.get(); cout << "5的阶乘是 " << result << endl; // 输出120 t.join(); return 0; }

四、std::shared_future:共享结果的容器

1. 作用

std::shared_futurestd::future共享版:可被拷贝,多个线程能通过不同的shared_future获取同一个结果(future是独占的,shared_future是共享的)。

std::shared_future的构造函数

1. 默认构造函数

shared_future() noexcept;

作用:创建一个 “空的”shared_future,不关联任何异步结果(valid()返回false)。

2. 移动构造函数(从std::future

shared_future(future<T>&& other) noexcept;

作用:用一个std::future移动构造shared_futurefuture会失效(转移了结果的所有权)。

这是最常用的构造方式之一(future::share()本质就是返回这种方式构造的shared_future)。

3. 拷贝构造函数

原型

shared_future(const shared_future& other) noexcept;

作用:拷贝另一个shared_future,两个shared_future关联同一个异步结果(这是shared_future实现 “共享结果” 的核心)。

4. 移动构造函数(从std::shared_future

原型

shared_future(shared_future&& other) noexcept;

作用:用另一个shared_future移动构造,shared_future会变成空的(转移了结果的所有权)。

2.std::shared_future核心成员函数

函数作用
const T& get() const阻塞线程(若任务未完成),返回结果;✅ 特点:可多次调用,不会失效。
void wait()阻塞线程直到任务完成,不获取结果。

3. 样例:多线程共享shared_future结果

#include <iostream> #include <future> #include <thread> #include <vector> using namespace std; // 异步任务:生成随机数 int generate_rand() { srand(time(0)); return rand() % 100; } // 线程函数:共享结果 void print_result(shared_future<int> fut, int thread_id) { int res = fut.get(); // 可多次调用 cout << "线程" << thread_id << "获取到的随机数:" << res << endl; } int main() { // 1. 启动异步任务,获取future future<int> fut = async(launch::async, generate_rand); // 2. 转换为shared_future(共享结果) shared_future<int> shared_fut = fut.share(); // 3. 启动3个线程共享结果 vector<thread> threads; for (int i = 0; i < 3; ++i) { threads.emplace_back(print_result, shared_fut, i); } // 等待线程完成 for (auto& t : threads) t.join(); return 0; }

运行结果(3 个线程拿到同一个随机数):

线程0获取到的随机数:42 线程1获取到的随机数:42 线程2获取到的随机数:42
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/26 8:30:50

如何用Qwen3-Embedding-0.6B提升RAG系统效果?答案在这

如何用Qwen3-Embedding-0.6B提升RAG系统效果&#xff1f;答案在这 1. 引言&#xff1a;RAG系统的瓶颈与嵌入模型的演进 在当前的检索增强生成&#xff08;Retrieval-Augmented Generation, RAG&#xff09;系统中&#xff0c;文本嵌入模型作为核心组件&#xff0c;直接影响着…

作者头像 李华
网站建设 2026/4/18 3:51:42

通义千问2.5-7B-Instruct运动健康:训练计划生成

通义千问2.5-7B-Instruct运动健康&#xff1a;训练计划生成 1. 引言 随着人工智能在个性化健康管理领域的深入应用&#xff0c;大语言模型&#xff08;LLM&#xff09;正逐步从通用对话系统演进为可落地的专业助手。通义千问 2.5-7B-Instruct 是阿里于 2024 年 9 月发布的 70…

作者头像 李华
网站建设 2026/4/25 2:27:07

NewBie-image-Exp0.1显存占用高?bfloat16推理优化实战案例解析

NewBie-image-Exp0.1显存占用高&#xff1f;bfloat16推理优化实战案例解析 1. 背景与问题提出 在当前生成式AI快速发展的背景下&#xff0c;大参数量的动漫图像生成模型逐渐成为内容创作和研究的重要工具。NewBie-image-Exp0.1作为基于Next-DiT架构的3.5B参数模型&#xff0c…

作者头像 李华
网站建设 2026/4/21 16:44:11

短视频平台敏感内容识别:Qwen3Guard实战应用案例

短视频平台敏感内容识别&#xff1a;Qwen3Guard实战应用案例 1. 引言&#xff1a;短视频内容安全的挑战与应对 随着短视频平台用户规模持续增长&#xff0c;平台每天产生的UGC&#xff08;用户生成内容&#xff09;数量呈指数级上升。海量视频标题、评论、弹幕和字幕中潜藏的…

作者头像 李华
网站建设 2026/4/18 3:45:10

PyTorch通用镜像在云平台部署:弹性GPU适配案例

PyTorch通用镜像在云平台部署&#xff1a;弹性GPU适配案例 1. 引言 随着深度学习模型复杂度的不断提升&#xff0c;开发与训练环境的一致性、可移植性和启动效率成为工程落地的关键瓶颈。尤其在云平台上进行大规模实验或生产级模型微调时&#xff0c;频繁搭建环境不仅耗时&am…

作者头像 李华
网站建设 2026/4/18 7:43:00

DeepSeek-R1-Distill-Qwen-1.5B医疗问答应用:本地知识库集成案例

DeepSeek-R1-Distill-Qwen-1.5B医疗问答应用&#xff1a;本地知识库集成案例 1. 引言&#xff1a;轻量级大模型在医疗场景的落地价值 随着大语言模型技术的发展&#xff0c;如何在资源受限的设备上实现高效、准确的智能服务成为关键挑战。尤其在医疗领域&#xff0c;对响应速…

作者头像 李华