C++ 异步编程:完整指南
现代应用程序需要高性能和响应性。C++ 中的异步编程允许执行耗时操作(输入输出、网络请求、复杂计算)而不会阻塞主线程。在本指南中,我们将解析 C++ 异步工作的关键机制:从经典的 std::thread 和 std::async 到现代的 C++20 协程。您将学习如何编写高效且安全的异步代码。
1. 基础:std::thread 和 std::async
从基本工具开始。std::thread 创建新的执行线程,但需要手动管理和同步。更方便的选项是 std::async,它异步启动函数并返回 std::future 以获取结果。
#include <iostream>#include <future>#include <chrono>
int long_running_task(int input) { std::this_thread::sleep_for(std::chrono::seconds(2)); return input * 10;}
int main() { std::cout << "启动异步任务..."; std::future<int> result = std::async(std::launch::async, long_running_task, 5); // 在任务执行期间做一些有用的事情 std::cout << "主线程继续工作..."; // 获取结果(如果任务尚未完成则阻塞) int value = result.get(); std::cout << "结果: " << value << std::endl; return 0;}关键点:
- std::launch::async — 保证在单独线程中启动。
- std::launch::deferred — 延迟执行直到调用
get()。 get()方法会阻塞线程直到获取结果。
2. 高级操作:std::promise 和 std::future
当需要将结果从一个线程传递到另一个线程时,使用 std::promise 和 std::future 对。promise 设置值,而 future 获取它。这在线程池或任务链中特别有用。
#include <iostream>#include <future>#include <thread>
void worker(std::promise<int> prom) { try { int result = 42; // 复杂计算 prom.set_value(result); } catch (...) { prom.set_exception(std::current_exception()); }}
int main() { std::promise<int> prom; std::future<int> fut = prom.get_future(); std::thread t(worker, std::move(prom)); // 获取结果 int value = fut.get(); std::cout << "获取的值: " << value << std::endl; t.join(); return 0;}重要特性:
promise不能复制,只能移动。- 异常通过
set_exception传递。 future只能使用一次(一次性获取)。
3. C++20 协程:现代方法
协程(coroutines)是 C++20 中添加的强大工具。它们允许暂停和恢复函数执行,而不阻塞线程。这对于异步输入输出操作和生成器非常理想。
#include <iostream>#include <coroutine>#include <future>
struct SimpleTask { struct promise_type { SimpleTask get_return_object() { return {}; } std::suspend_never initial_suspend() { return {}; } std::suspend_never final_suspend() noexcept { return {}; } void return_void() {} void unhandled_exception() { std::exit(1); } };};
SimpleTask async_operation() { std::cout << "协程开始";