在 C++ 中实现异步调用有多种方法,以下是一些最佳实践:
<future>
和 <thread>
库:<future>
和 <thread>
库提供了基本的线程和异步操作支持。通过 std::async
、std::packaged_task
和 std::promise
,您可以创建和管理异步任务。#include <iostream>
#include <future>
#include <thread>
int compute(int x, int y) {
return x + y;
}
int main() {
// 创建异步任务
std::future<int> result = std::async(compute, 2, 3);
// 在异步任务完成之前执行其他工作
std::cout << "Waiting for computation...\n";
// 获取异步任务的结果
int sum = result.get();
std::cout << "Computation result: " << sum << std::endl;
return 0;
}
std::jthread
和 std::future_value
:C++20 引入了 std::jthread
,它可以自动管理线程的生命周期。同时,std::future_value
可以用于封装特定类型的未来结果。#include <iostream>
#include <future>
#include <jthread>
int compute(int x, int y) {
return x + y;
}
int main() {
// 创建异步任务
std::packaged_task<int(int, int)> task(compute);
std::future<int> result = task.get_future();
// 创建 jthread 运行异步任务
std::jthread thread(std::move(task), 2, 3);
// 在异步任务完成之前执行其他工作
std::cout << "Waiting for computation...\n";
// 获取异步任务的结果
int sum = result.get();
// 等待线程结束
thread.join();
std::cout << "Computation result: " << sum << std::endl;
return 0;
}
std::async
的 std::launch
策略:通过指定 std::launch
策略,您可以控制异步任务的启动方式。例如,您可以使用 std::launch::async
和 std::launch::deferred
来指定任务立即启动或在调用 get()
方法时启动。#include <iostream>
#include <future>
int compute(int x, int y) {
return x + y;
}
int main() {
// 创建异步任务,立即启动
std::future<int> result = std::async(std::launch::async, compute, 2, 3);
// 在异步任务完成之前执行其他工作
std::cout << "Waiting for computation...\n";
// 获取异步任务的结果
int sum = result.get();
std::cout << "Computation result: " << sum << std::endl;
return 0;
}
避免使用全局或静态异步任务:全局或静态异步任务可能导致资源竞争和同步问题。尽量将异步任务封装在类或函数中,并确保正确地管理线程同步。
合理地处理异常:当异步任务抛出异常时,需要确保正确地捕获和处理这些异常。可以使用 std::future::get()
的重载版本来捕获异常。
考虑使用线程池:对于大量并发任务,可以考虑使用线程池来限制线程数量并提高性能。C++ 标准库没有提供线程池的实现,但您可以自己实现或使用第三方库(如 Intel Threading Building Blocks (TBB))。