線程
類std::thread代表一個可執行線程,使用時必須包含頭文件<thread>。std::thread可以和普通函數,匿名函數和仿函數一個實現了operator()函數的類)一同使用。另外,它允許向線程函數傳遞任意數量的參數。
- #include <thread>
- void func()
- {
- // do some work
- }
- int main()
- {
- std::thread t(func);
- t.join();
- return 0;
- }
上例中,t 是一個線程對象,函數func()運行於該線程中。對join()函數的調用將使調用線程本例是指主線程)一直處於阻塞狀態,直到正在執行的線程t執行結束。如果線程函數返回某個值,該值也將被忽略。不過,該函數可以接收任意數量的參數。
- void func(int i, double d, const std::string& s)
- {
- std::cout << i << ", " << d << ", " << s << std::endl;
- }
- int main()
- {
- std::thread t(func, 1, 12.50, "sample");
- t.join();
- return 0;
- }
盡管可以向線程函數傳遞任意數量的參數,但是所有的參數應當按值傳遞。如果需要將參數按引用傳遞,那要向下例所示那樣,必須將參數用std::ref 或者std::cref進行封裝。
- void func(int& a)
- {
- a++;
- }
- int main()
- {
- int a = 42;
- std::thread t(func, std::ref(a));
- t.join();
- std::cout << a << std::endl;
- return 0;
- }
該程序打印結果為43,但是如果不用std::ref把參數a進行封裝的話,輸出結果將為42.
除了join方法外,該線程類還提供了另外兩個方法:
swap:交換兩個線程對象的底層句柄。
Detach: 允許執行該方法的線程脫離其線程對象而繼續獨立執行。脫離後的線程不再是可結合線程你不能等待它們執行結束)。
- int main()
- {
- std::thread t(funct);
- t.detach();
- return 0;
- }
有一點非常重要,如果線程函數拋出異常,使用常規的try-catch語句是捕獲不到該異常的。換句話說,以下的做法是不可行的:
- try
- {
- std::thread t1(func);
- std::thread t2(func);
- t1.join();
- t2.join();
- }
- catch(const std::exception& ex)
- {
- std::cout << ex.what() << std::endl;
- }
要在線程間傳遞異常,你需要在線程函數中捕獲他們,將其存儲在合適的地方,比便於另外的線程可以隨後獲取到這些異常。
- std::mutex g_mutex;
- std::vector<std::exception_ptr> g_exceptions;
- void throw_function()
- {
- throw std::exception("something wrong happened");
- }
- void func()
- {
- try
- {
- throw_function();
- }
- catch(...)
- {
- std::lock_guard<std::mutex> lock(g_mutex);
- g_exceptions.push_back(std::current_exception());
- }
- }
- int main()
- {
- g_exceptions.clear();
- std::thread t(func);
- t.join();
- for(auto& e : g_exceptions)
- {
- try
- {
- if(e != nullptr)
- {
- std::rethrow_exception(e);
- }
- }
- catch(const std::exception& e)
- {
- std::cout << e.what() << std::endl;
- }
- }
- return 0;
- }
想要知道更多的關於捕獲和傳遞異常的知識,可以閱讀這兩本書在主線程中處理輔助線程拋出的C++異常和怎樣在線程間傳遞異常。
在深入學習之前,有一點需要注意 <thread>頭文件在命名空間std::this_thread中提供了一些幫助函數: