這個系列是我近期學習 C++ 併發編程的總結,文章和代碼最初都是基於 Boost.Thread,可是最近愈來愈發現,STL 內置的線程和同步工具已經足夠完善了。ios
STL 和 Boost 線程,在設計和用法上極其類似,一旦掌握了一個,不難切換到另外一個。若是非要比較的話,Boost 更完善一些,好比 Boost 提供了 thread_group
和 upgrade_lock
,STL 則沒有。編程
此節介紹「線程的建立」。併發
經過一個不帶參數的函數建立線程。函數
#include <iostream> #include <thread> void Hello() { // 睡眠一秒以模擬數據處理。 std::this_thread::sleep_for(std::chrono::seconds(1)); std::cout << "Hello, World!" << std::endl; } int main() { // 建立一個線程對象,注意函數 Hello 將當即運行。 std::thread t(&Hello); // 等待線程結束。 // 不然線程還沒執行(完),主程序就已經結束了。 t.join(); return 0; }
經過一個帶參數的函數建立線程。工具
#include <iostream> #include <thread> void Hello(const char* what) { // 睡眠一秒以模擬數據處理。 std::this_thread::sleep_for(std::chrono::seconds(1)); std::cout << "Hello, " << what << "!" << std::endl; } int main() { std::thread t(&Hello, "World"); // 等價於使用 bind: // std::thread t(std::bind(&Hello, "World")); t.join(); return 0; }
經過一個函數對象——即仿函數(functor)——建立線程。學習
#include <iostream> #include <thread> class Hello { public: void operator()(const char* what) { std::this_thread::sleep_for(std::chrono::seconds(1)); std::cout << "Hello, " << what << "!" << std::endl; } }; int main() { Hello hello; // 方式一:拷貝函數對象。 std::thread t1(hello, "World"); t1.join(); // 方式二:不拷貝函數對象,經過 boost::ref 傳入引用。 // 用戶必須保證被線程引用的函數對象,擁有超出線程的生命期。 // 好比這裏經過 join 線程保證了這一點。 std::thread t2(std::ref(hello), "World"); t2. return 0; }
經過一個成員函數建立線程。
與前例不一樣之處在於,須要以 bind
綁定 this
指針做爲第一個參數。this
#include <iostream> #include <thread> class Hello { public: Hello() { std::thread t(std::bind(&Hello::Entry, this, "World")); t.join(); } private: // 線程函數 void Entry(const char* what) { std::this_thread::sleep_for(std::chrono::seconds(1)); std::cout << "Hello, " << what << "!" << std::endl; } }; int main() { Hello hello; return 0; }
建立兩個線程,各自倒着計數。
此例順帶演示了 detached 線程,被 detached 的線程,自生自滅,不受控制,沒法再 join。線程
#include <iostream> #include <thread> class Counter { public: Counter(int value) : value_(value) { } void operator()() { while (value_ > 0) { std::cout << value_ << " "; --value_; std::this_thread::sleep_for(std::chrono::seconds(1)); } std::cout << std::endl; } private: int value_; }; int main() { std::thread t1(Counter(3)); t1.join(); std::thread t2(Counter(3)); t2.detach(); // 等待幾秒,否則 t2 根本沒機會執行。 std::this_thread::sleep_for(std::chrono::seconds(4)); return 0; }