C++并发编程实战:深入理解异步任务提供者std::promise

C++并发编程实战:深入理解异步任务提供者std::promise

Cplusplus-Concurrency-In-Practice A Detailed Cplusplus Concurrency Tutorial 《C++ 并发编程指南》 Cplusplus-Concurrency-In-Practice 项目地址: https://gitcode.com/gh_mirrors/cp/Cplusplus-Concurrency-In-Practice

前言

在现代C++并发编程中,<future>头文件提供了一系列强大的工具来处理异步操作。本文将重点介绍其中的异步任务提供者(Provider)之一——std::promise类,帮助开发者掌握线程间通信和同步的核心技术。

std::promise概述

std::promise是C++11引入的一个模板类,它提供了一种在线程间传递值的机制。简单来说,promise对象就像是一个"承诺",它承诺在未来某个时刻会提供一个值,而这个值可以通过与之关联的std::future对象获取。

核心概念

  1. 共享状态(shared state):promise和future共同维护的存储区域,用于保存值或异常
  2. 异步提供者(Provider):promise负责设置共享状态的值
  3. 异步消费者:future负责获取共享状态的值

std::promise的构造函数

std::promise提供了多种构造函数:

// 默认构造函数
std::promise<int> p1;

// 带分配器的构造函数
std::promise<int> p2(std::allocator_arg, my_allocator);

// 移动构造函数
std::promise<int> p3(std::move(p1));

需要注意的是:

  • promise禁止拷贝构造
  • 普通赋值操作被禁用,只有移动语义

核心成员函数详解

get_future()

std::future<T> get_future();

此函数返回与promise共享状态关联的future对象。关键点:

  • 每个promise只能调用一次get_future()
  • 如果多次调用会抛出std::future_error异常
  • 调用后,promise和future共享相同的状态

set_value()系列

void set_value(const T& val);
void set_value(T&& val);

设置共享状态的值并使状态变为ready。使用时要注意:

  • 只能调用一次set_value()
  • 如果共享状态已有值或异常会抛出std::future_error
  • 有多个重载版本处理不同情况

set_exception()

void set_exception(std::exception_ptr p);

设置共享状态的异常对象。典型使用场景:

try {
    // 可能抛出异常的操作
} catch(...) {
    prom.set_exception(std::current_exception());
}

set_value_at_thread_exit()

void set_value_at_thread_exit(const T& val);

特殊版本的set_value():

  • 设置值但不立即标记为ready
  • 当线程退出时自动标记为ready
  • 避免过早唤醒等待线程

典型使用模式

基本值传递

std::promise<int> prom;
std::future<int> fut = prom.get_future();

std::thread t([&prom]{
    prom.set_value(42);  // 设置值
});

std::cout << fut.get();  // 获取值
t.join();

异常传递

std::promise<void> prom;
std::future<void> fut = prom.get_future();

std::thread t([&prom]{
    try {
        throw std::runtime_error("Error!");
    } catch(...) {
        prom.set_exception(std::current_exception());
    }
});

try {
    fut.get();
} catch(const std::exception& e) {
    std::cerr << e.what();
}
t.join();

注意事项

  1. 生命周期管理:确保promise和关联的future生命周期足够长
  2. 单次使用:每个set方法只能调用一次
  3. 线程安全:promise对象本身不是线程安全的
  4. 性能考虑:频繁创建promise/future对会有一定开销

总结

std::promisestd::future的组合为C++并发编程提供了强大的线程间通信机制。通过本文的详细讲解,读者应该能够:

  • 理解promise/future的工作原理
  • 掌握各种成员函数的正确用法
  • 在实际项目中合理应用这一模式
  • 避免常见的陷阱和错误用法

正确使用这些工具可以大大简化多线程程序的编写,提高代码的可维护性和可靠性。

Cplusplus-Concurrency-In-Practice A Detailed Cplusplus Concurrency Tutorial 《C++ 并发编程指南》 Cplusplus-Concurrency-In-Practice 项目地址: https://gitcode.com/gh_mirrors/cp/Cplusplus-Concurrency-In-Practice

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乔嫣忱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值