首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++11 新特性:std::future 與 std::async 非同步編程詳解

     編輯:關於C++

為什麼需要 std::future / std::async?

傳統多執行緒寫法:建立 std::thread,執行緒函數將結果寫入共享變數,主執行緒用 join() 或條件變數等待。這樣不僅樣板代碼多,還易出現競態條件。C++11 引入 std::future 與 std::async,提供「異步任務 + 未來結果」的高層抽象,讓非同步編程像同步調用一樣簡單。

核心概念

  • std::future<T>:持有共享狀態,提供 get()(阻塞直到結果就緒並取值)、wait()、wait_for()、wait_until() 等方法。
  • std::async:啟動異步任務,返回 std::future。內部自動處理 std::promise、std::packaged_task 等底層機制。
  • 啟動策略:
    • std::launch::async:立即建立新執行緒執行(真正的並行)。
    • std::launch::deferred:延遲執行,直到調用 future.get() 或 wait() 時才在當前執行緒同步執行。
    • 預設策略為 async | deferred,由實現決定(通常優先用 async)。

基本用法範例

#include <iostream>
#include <future>
#include <chrono>

bool is_prime(int x) {
    for (int i = 2; i < x; ++i)
        if (x % i == 0) return false;
    return true;
}

int main() {
    // 啟動異步任務,預設策略
    std::future<bool> fut = std::async(is_prime, 444444443);

    // 主執行緒做其他事,同時輪詢進度
    std::cout << "checking, please wait";
    std::chrono::milliseconds span(100);
    while (fut.wait_for(span) == std::future_status::timeout) {
        std::cout << '.' << std::flush;
    }

    bool result = fut.get(); // 取得結果(若尚未完成會阻塞)
    std::cout << "\n444444443 " << (result ? "is" : "is not") << " prime.\n";
    return 0;
}

指定啟動策略與狀態檢查

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

std::cout << "waiting...";
std::future_status status;
do {
    status = fut.wait_for(std::chrono::seconds(1));
    if (status == std::future_status::deferred) std::cout << " deferred";
    else if (status == std::future_status::timeout) std::cout << " timeout";
    else if (status == std::future_status::ready) std::cout << " ready!";
} while (status != std::future_status::ready);

std::cout << "\nresult is " << fut.get() << '\n';

std::async vs 手動 thread + promise

std::async 封裝了 packaged_task + promise + future 的完整流程,開發者無需手動管理共享狀態、異常傳播、執行緒生命週期。對於「啟動任務、稍後取結果」的典型場景,std::async 是首選;若需精細控制執行緒池、任務佇列、取消機制,則仍需底層 API 或第三方庫(如 Boost.Thread、Intel TBB)。

注意事項

  • future.get() 只能調用一次,調用後共享狀態被釋放。
  • 若 future 析構時共享狀態尚未就緒且非 deferred,析構函數會阻塞(等同隱式 wait()),可能導致效能問題。解決方法:用 std::move 轉移 ownership 或提前 wait()。
  • Lambda 捕獲引用變數時需確保生命週期覆蓋異步任務。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved