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

C++ 並行編程(二):線程啟動、等待、異常安全與分離

     編輯:C++ 入門

C++ 並行編程(二):線程啟動、等待、異常安全與分離

接上篇,詳細講解 std::thread 的構造、同步、異常處理及後台運行模式。

1. 啟動線程的多種方式

void do_work(); // 普通函數
std::thread t1(do_work);

struct Task { void operator()() { /*...*/ } }; // 仿函數
std::thread t2(Task()); // 注意:最 vexing parse!應寫
std::thread t2((Task())); // 或 C++11 統一初始化
std::thread t2{Task()};

auto lambda = []{ /*...*/ };
std::thread t3(lambda);

關鍵點:std::thread t(Task()) 被解析為函數聲明,需加額外括號或用花括號初始化。

2. 等待線程:join() vs detach()

  • join():阻塞當前線程,直到目標線程結束。只能調用一次,之後 joinable() == false。
  • detach():線程獨立運行,不再與 thread 對象關聯。主線程結束不等待它,但需確保線程不訪問已銷毀的局部變量。
void oops() {
    int local = 0;
    std::thread t([&]{ for(int i=0;i<1e6;++i) ++local; });
    t.detach(); // 危險!t 可能訪問已銷毀的 local
}

3. 異常安全:確保線程被 join

若主線程拋出異常未捕獲,detach 線程可能訪問無效內存;join 未調用則資源洩漏。兩種模式:

// 模式一:try-catch
std::thread t(func);
try {
    do_other_work();
} catch (...) {
    if (t.joinable()) t.join();
    throw;
}

// 模式二:RAII 守衛(推薦)
class thread_guard {
    std::thread& t;
public:
    explicit thread_guard(std::thread& t_) : t(t_) {}
    ~thread_guard() { if (t.joinable()) t.join(); }
    thread_guard(const thread_guard&) = delete;
    thread_guard& operator=(const thread_guard&) = delete;
};
void safe() {
    std::thread t(func);
    thread_guard g(t);
    do_other_work(); // 異常拋出時 g 析構自動 join
}

4. 後台運行線程

適用於無需等待、獨立任務(如 Word 多文檔編輯)。調用 detach() 後,線程生命週期由運行時管理。需保證線程不依賴主線程棧上變量,通常傳遞共享指針或複製數據。

總結

  • 啟動:傳入可調用對象,注意 most vexing parse。
  • 同步:優先用 join(),配合 RAII 守衛確保異常安全。
  • 分離:detach() 仅用於真正獨立、無共享棧變量的後台任務。
  • 核心原則:線程對象銷毀前必須 join 或 detach,否則 std::terminate。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved