程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++11 中的線程、鎖和條件變量(1)

C++11 中的線程、鎖和條件變量(1)

編輯:C++入門知識

線程

類std::thread代表一個可執行線程,使用時必須包含頭文件<thread>。std::thread可以和普通函數,匿名函數和仿函數一個實現了operator()函數的類)一同使用。另外,它允許向線程函數傳遞任意數量的參數。

  1. #include <thread> 
  2.   
  3. void func() 
  4.    // do some work 
  5.   
  6. int main() 
  7.    std::thread t(func); 
  8.    t.join(); 
  9.   
  10.    return 0; 

上例中,t 是一個線程對象,函數func()運行於該線程中。對join()函數的調用將使調用線程本例是指主線程)一直處於阻塞狀態,直到正在執行的線程t執行結束。如果線程函數返回某個值,該值也將被忽略。不過,該函數可以接收任意數量的參數。

  1. void func(int i, double d, const std::string& s) 
  2.     std::cout << i << ", " << d << ", " << s << std::endl; 
  3.   
  4. int main() 
  5.    std::thread t(func, 1, 12.50, "sample"); 
  6.    t.join(); 
  7.   
  8.    return 0; 

盡管可以向線程函數傳遞任意數量的參數,但是所有的參數應當按值傳遞。如果需要將參數按引用傳遞,那要向下例所示那樣,必須將參數用std::ref 或者std::cref進行封裝。

  1. void func(int& a) 
  2.    a++; 
  3.   
  4. int main() 
  5.    int a = 42; 
  6.    std::thread t(func, std::ref(a)); 
  7.    t.join(); 
  8.   
  9.    std::cout << a << std::endl; 
  10.   
  11.    return 0; 

該程序打印結果為43,但是如果不用std::ref把參數a進行封裝的話,輸出結果將為42.

除了join方法外,該線程類還提供了另外兩個方法:

swap:交換兩個線程對象的底層句柄。

Detach: 允許執行該方法的線程脫離其線程對象而繼續獨立執行。脫離後的線程不再是可結合線程你不能等待它們執行結束)。

  1. int main() 
  2.     std::thread t(funct); 
  3.     t.detach(); 
  4.   
  5.     return 0; 

有一點非常重要,如果線程函數拋出異常,使用常規的try-catch語句是捕獲不到該異常的。換句話說,以下的做法是不可行的:

  1. try 
  2.     std::thread t1(func); 
  3.     std::thread t2(func); 
  4.   
  5.     t1.join(); 
  6.     t2.join(); 
  7. catch(const std::exception& ex) 
  8.     std::cout << ex.what() << std::endl; 

要在線程間傳遞異常,你需要在線程函數中捕獲他們,將其存儲在合適的地方,比便於另外的線程可以隨後獲取到這些異常。

  1. std::mutex                       g_mutex; 
  2. std::vector<std::exception_ptr>  g_exceptions; 
  3.   
  4. void throw_function() 
  5.    throw std::exception("something wrong happened"); 
  6.   
  7. void func() 
  8.    try 
  9.    { 
  10.       throw_function(); 
  11.    } 
  12.    catch(...) 
  13.    { 
  14.       std::lock_guard<std::mutex> lock(g_mutex); 
  15.       g_exceptions.push_back(std::current_exception()); 
  16.    } 
  17.   
  18. int main() 
  19.    g_exceptions.clear(); 
  20.   
  21.    std::thread t(func); 
  22.    t.join(); 
  23.   
  24.    for(auto& e : g_exceptions) 
  25.    { 
  26.       try 
  27.       { 
  28.          if(e != nullptr) 
  29.          { 
  30.             std::rethrow_exception(e); 
  31.          } 
  32.       } 
  33.       catch(const std::exception& e) 
  34.       { 
  35.          std::cout << e.what() << std::endl; 
  36.       } 
  37.    } 
  38.   
  39.    return 0; 

想要知道更多的關於捕獲和傳遞異常的知識,可以閱讀這兩本書在主線程中處理輔助線程拋出的C++異常怎樣在線程間傳遞異常

在深入學習之前,有一點需要注意 &lt;thread&gt;頭文件在命名空間std::this_thread中提供了一些幫助函數:

  • get_id: 返回當前線程的id.
  • yield:在處於等待狀態時,可以讓調度器先運行其他可用的線程。
  • sleep_for:阻塞當前線程,時間不少於其參數指定的時間。
  • sleep_util:在參數指定的時間到達之前,使當前線程一直處於阻塞狀態。


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved