在 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))。