Skip to content

std::future & promise

future/promise 是 C++ 异步编程的基础,提供线程间传递值和异常的标准机制。

future 与 promise

cpp
#include <future>
#include <thread>

// promise:写端(生产者)
// future:读端(消费者)

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

// 在另一个线程中设置值
std::thread t([&prom] {
    std::this_thread::sleep_for(std::chrono::seconds(1));
    prom.set_value(42);  // 设置结果
});

// 主线程等待结果
int result = fut.get();  // 阻塞直到有值
std::cout << result << "\n";  // 42
t.join();

// 传递异常
std::promise<int> prom2;
std::future<int> fut2 = prom2.get_future();

std::thread t2([&prom2] {
    try {
        throw std::runtime_error("计算失败");
    } catch (...) {
        prom2.set_exception(std::current_exception());
    }
});

try {
    int val = fut2.get();  // 重新抛出异常
} catch (const std::exception& e) {
    std::cout << "异常: " << e.what() << "\n";
}
t2.join();

std::async

cpp
#include <future>

// async:最简单的异步执行方式
auto fut = std::async(std::launch::async, []() -> int {
    std::this_thread::sleep_for(std::chrono::seconds(1));
    return 42;
});

// 做其他工作...
std::cout << "等待结果...\n";

int result = fut.get();  // 等待并获取结果
std::cout << "结果: " << result << "\n";

// 启动策略
std::launch::async   // 立即在新线程执行
std::launch::deferred // 延迟执行(调用 get() 时在当前线程执行)
std::launch::async | std::launch::deferred  // 由实现决定(默认)

// 并行计算示例
auto f1 = std::async(std::launch::async, compute_part1);
auto f2 = std::async(std::launch::async, compute_part2);
auto f3 = std::async(std::launch::async, compute_part3);

auto r1 = f1.get();
auto r2 = f2.get();
auto r3 = f3.get();
auto total = combine(r1, r2, r3);

packaged_task

cpp
#include <future>

// packaged_task:将函数包装为可异步执行的任务
std::packaged_task<int(int, int)> task([](int a, int b) {
    return a + b;
});

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

// 在另一个线程执行
std::thread t(std::move(task), 3, 4);
t.join();

std::cout << fut.get() << "\n";  // 7

// 用于线程池
class SimplePool {
    std::vector<std::thread> workers_;
    std::queue<std::packaged_task<void()>> tasks_;
    std::mutex mtx_;
    std::condition_variable cv_;
    bool stop_ = false;

public:
    template<typename F>
    auto submit(F&& f) {
        using R = std::invoke_result_t<F>;
        std::packaged_task<R()> task(std::forward<F>(f));
        auto fut = task.get_future();
        {
            std::lock_guard lock(mtx_);
            tasks_.emplace([t = std::move(task)]() mutable { t(); });
        }
        cv_.notify_one();
        return fut;
    }
};

shared_future

cpp
// future 只能 get() 一次,shared_future 可以多次
std::promise<std::string> prom;
std::shared_future<std::string> shared = prom.get_future().share();

// 多个线程等待同一个结果
std::vector<std::thread> threads;
for (int i = 0; i < 5; ++i) {
    threads.emplace_back([shared, i] {
        auto result = shared.get();  // 所有线程都能获取
        std::cout << "线程 " << i << " 收到: " << result << "\n";
    });
}

prom.set_value("广播消息");
for (auto& t : threads) t.join();

超时等待

cpp
std::future<int> fut = std::async(std::launch::async, []() {
    std::this_thread::sleep_for(std::chrono::seconds(5));
    return 42;
});

// 等待一段时间
auto status = fut.wait_for(std::chrono::seconds(1));
switch (status) {
    case std::future_status::ready:
        std::cout << "结果: " << fut.get() << "\n";
        break;
    case std::future_status::timeout:
        std::cout << "超时,继续等待...\n";
        break;
    case std::future_status::deferred:
        std::cout << "延迟执行\n";
        break;
}

// 等待到特定时间点
auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(2);
if (fut.wait_until(deadline) == std::future_status::ready) {
    std::cout << fut.get() << "\n";
}

关键认知

std::async 是最简单的异步方式,但注意:返回的 future 析构时会阻塞等待(不要忽略返回值!)。packaged_task 适合线程池场景。shared_future 用于广播结果给多个等待者。

系统学习 C++ 生态,深入底层架构