<thread>頭文件中包含thread類與this_thread命名空間,下面逐一介紹。
thread類
1. 構造函數
(1)默認構造函數
thread() noexcept;
默認構造函數不執行任何線程,產生線程對象的線程ID為0。
(2)初始化構造函數
template <class Fn, class... Args>
explicit thread (Fn&& fn, Args&&... args);
產生一個thread對象,提供一個joinable的線程並開始執行。joinable的線程在它們被銷毀前需要被join或detach(否則線程資源不會被完全釋放)。
參數介紹:
fn: 指向函數的指針,指向成員函數的指針,或者任何有移動構造函數(?)的對象(例如重載了operator()的類對象,閉包和函數對象)。如果有返回值的話,返回值被丟棄。
arg…: 傳遞給fn的參數。它們的類型必須是可移動構造的(?)。如果fn是成員函數指針的話,第一個參數必須是調用此方法的對象(或者引用/指針)。
(3)拷貝構造函數
thread (const thread&) = delete;
刪除拷貝構造函數(線程對象不能被拷貝)。
(4)移動構造函數
thread (thread&& x) noexcept;
如果x是一個線程的話,生成一個新的線程對象。這個操作不影響原線程運行,只是將線程的擁有者從x變為新對象,此時x不再代表任何線程(移交了控制權)。
參數介紹:
x: 要移動給構造構造函數的另一線程對象。
例子
// constructing threads #include <iostream> // std::cout #include <atomic> // std::atomic #include <thread> // std::thread #include <vector> // std::vector std::atomic<int> global_counter (0); void increase_global (int n) { for (int i=0; i<n; ++i) ++global_counter; } void increase_reference (std::atomic<int>& variable, int n) { for (int i=0; i<n; ++i) ++variable; } struct C : std::atomic<int> { C() : std::atomic<int>(0) {} void increase_member (int n) { for (int i=0; i<n; ++i) fetch_add(1); } }; int main () { std::vector<std::thread> threads; std::cout << "increase global counter with 10 threads...\n"; for (int i=1; i<=10; ++i) threads.push_back(std::thread(increase_global,1000)); std::cout << "increase counter (foo) with 10 threads using reference...\n"; std::atomic<int> foo(0); for (int i=1; i<=10; ++i) threads.push_back(std::thread(increase_reference,std::ref(foo),1000)); std::cout << "increase counter (bar) with 10 threads using member...\n"; C bar; for (int i=1; i<=10; ++i) threads.push_back(std::thread(&C::increase_member,std::ref(bar),1000)); std::cout << "synchronizing all threads...\n"; for (auto& th : threads) th.join(); std::cout << "global_counter: " << global_counter << '\n'; std::cout << "foo: " << foo << '\n'; std::cout << "bar: " << bar << '\n'; return 0; }
顯示結果
increase global counter using 10 threads... increase counter (foo) with 10 threads using reference... increase counter (bar) with 10 threads using member... synchronizing all threads... global_counter: 10000 foo: 10000 bar: 10000
2. 析構函數
~thread();
如果線程是joinable的,在銷毀時會調用terminate();
3. 成員函數
(1)void detach();
使該線程不再由調用線程的對象所管理(意味著調用線程不用再使用join方法),讓該線程自己獨立的運行。兩個線程均不再阻塞,同步執行。當一個線程結束執行時,回釋放它自己使用的資源。當調用了這個方法後,線程對象變成non-joinable狀態,可以被安全刪除。
例子
#include <iostream> // std::cout #include <thread> // std::thread, std::this_thread::sleep_for #include <chrono> // std::chrono::seconds void pause_thread(int n) { std::this_thread::sleep_for (std::chrono::seconds(n)); std::cout << "pause of " << n << " seconds ended\n"; } int main() { std::cout << "Spawning and detaching 3 threads...\n"; std::thread (pause_thread,1).detach(); std::thread (pause_thread,2).detach(); std::thread (pause_thread,3).detach(); std::cout << "Done spawning threads.\n"; std::cout << "(the main thread will now pause for 5 seconds)\n"; // give the detached threads time to finish (but not guaranteed!): pause_thread(5); return 0; }
結果
Spawning and detaching 3 threads... Done spawning threads. (the main thread will now pause for 5 seconds) pause of 1 seconds ended pause of 2 seconds ended pause of 3 seconds ended pause of 5 seconds ended
(2)id get_id() const noexcept;
取得線程id
如果線程對象是joinable的,這個方法返回一個唯一的線程id。
如果線程對象不是joinable的,這個方法返回默認構造對象的id(為0)。
(3)void join();
調用這個函數的主線程會被阻塞直到子線程結束,子線程結束後有一些資源通過主線程回收。當調用這個函數之後,子線程對象變成non-joinable狀態,可以安全銷毀。該函數目的是防止主線程在子線程結束前銷毀,導致資源未成功回收。
例子
// example for thread::join #include <iostream> // std::cout #include <thread> // std::thread, std::this_thread::sleep_for #include <chrono> // std::chrono::seconds void pause_thread(int n) { std::this_thread::sleep_for (std::chrono::seconds(n)); std::cout << "pause of " << n << " seconds ended\n"; } int main() { std::cout << "Spawning 3 threads...\n"; std::thread t1 (pause_thread,1); std::thread t2 (pause_thread,2); std::thread t3 (pause_thread,3); std::cout << "Done spawning threads. Now waiting for them to join:\n"; t1.join(); t2.join(); t3.join(); std::cout << "All threads joined!\n"; return 0; }
結果
Spawning 3 threads... Done spawning threads. Now waiting for them to join: pause of 1 seconds ended pause of 2 seconds ended pause of 3 seconds ended All threads joined!
(4)bool joinable() const noexcept;
返回線程的joinable狀態。
如果一個線程對象是作為一個線程執行的它就是joinable的。
當線程是如下情況的時候就不是joinable的
a. 如果是用默認構造函數產生的(未執行)。
b. 如果它曾被作為移動構造函數的參數(x)。
c. 如果它曾被join或者detach過。
(5)native_handle_type native_handle();
返回A value of member type thread::native_handle_type.
待續…