參考:
http://www.oschina.net/translate/cplusplus-11-threading-make-your-multitasking-life
http://blog.jobbole.com/44409/
線程
類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執行結束。如果線程函數返回某個值,該值也將被忽略。不過,該函數可以接收任意數量的參數。
1 void func(int i, double d, const std::string& s) 2 { 3 std::cout << i << ", " << d << ", " << s << std::endl; 4 } 5 6 int main() 7 { 8 std::thread t(func, 1, 12.50, "sample"); 9 t.join(); 10 11 return 0; 12 }
盡管可以向線程函數傳遞任意數量的參數,但是所有的參數應當按值傳遞。如果需要將參數按引用傳遞,那要向下例所示那樣,必須將參數用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
Detach: 允許執行該方法的線程脫離其線程對象而繼續獨立執行。脫離后的線程不再是可結合線程(你不能等待它們執行結束)。
int main() { std::thread t(funct); t.detach(); return 0; }
互斥Mutex
C++ 11的<mutex>頭文件里包含了四種不同的互斥量:
- Mutex: 提供了核心函數 lock() 和 unlock(),以及非阻塞方法的try_lock()方法,一旦互斥量不可用,該方法會立即返回。
- Recursive_mutex:允許在同一個線程中對一個互斥量的多次請求。
- Timed_mutex:同上面的mutex類似,但它還有另外兩個方法 try_lock_for() 和 try_lock_until(),分別用於在某個時間段里或者某個時刻到達之間獲取該互斥量。
- Recursive_timed_mutex: 結合了timed_mutex 和recuseive_mutex的使用。
std::mutex與win32的臨界區(cirtical section)很類似。lock()如同EnterCriticalSection,unlock如同LeaveCriticalSection,try_lock則像TryEnterCriticalSection。
std::mutex m; int j = 0; void foo() { m.lock(); // 進入臨界區域 j++; m.unlock(); // 離開 } void func() { std::thread t1(foo); std::thread t2(foo); t1.join(); t2.join(); // j = 2; }
如上,你在lock一個 std::mutex 對象之后必須解鎖(unlock)。如果你已經對其加鎖,你不能再次lock。這與win32 不同,如果你已經在臨界區(critical section)里,再次 EnterCriticalSection不會失敗,但是會增加一個計數。
嗨,不要走開哦。前面提到不能對std::mutex重復lock。這里有std::recursive_mutex(誰發明的這名字),它的行為則與臨界區(critical section)相似,可以重復lock。
std::recursive_mutex m; void foo() { m.lock(); m.lock(); // now valid j++; m.unlock(); m.unlock(); // don't forget! }