std::thread線程詳解(1)
目錄
簡介
本文主要介紹了標準庫中的線程部分。線程是目前多核編程裏面最重要的一部分。
與進程進程相比,其所需的資源更少,線程之間溝通的方法更多; 他們之間的區別可以比較簡明用以下幾點概括[1]:
- 進程是資源分配的最小單位,線程是CPU調度的最小單位;也就是說進程之間的資源是相互隔離,而線程之間的是可以相互訪問的。
- 線程的存在依賴於進程,一個進程可以保護多個線程;
- 進程出現錯誤不會影響其他進程,但是一個線程出現錯誤,會影響同一進程下的所有線程。
線程的使用
線程的創建
一般使用std::thread
創建一個線程。std::thread
支持輸入一個函數對象,及一些參數,類似於std::bind
,不過沒有佔位符。
最常見,最簡單的是對輸入一個匿名函數作為參數:
std::thread t1([]() {
std::cout << "Hello World" << std::endl;
});
t1.join();
需要注意的是,在使用多線程的時候,如果使用類似於std::cout << "Hello World" << std::endl;
的語句,容易造成輸出的混亂。比如
std::thread t1([]() {
std::cout << "Hello World1" << std::endl;
});
std::thread t2([]() {
std::cout << "Hello World2" << std::endl;
});
t1.join();
t2.join();
以上代碼,我們一般來說期望的輸出是
但是,在一些情況下,它還會以以下的方法輸出
造成這個的原因很簡單,因為"Hello World"
和std::endl
的輸出是分開的,所以他們之間可能被插入其他的輸出。為了解決這個問題。一般會使用一個完整的字符串進行輸出,但是C++在格式化這一方面做的比較差(C++20
的format
庫看起來還不錯),所以一般情況下會使用printf
輸出。
線程的方法和屬性
-
joinable()
判斷線程是否可連接(可執行線程)的,有以下情況的,為不可連接的:- 構造時,
thread()
沒有參數; - 該對象的線程已經被移動了;
- 該線程已經被
join
或detach
;
- 構造時,
-
get_id()
返回線程的ID; -
native_handle()
返回POSIX
標準的線程對象; -
join()
等待線程執行完成; -
detach()
分離線程,分離後對象不再擁有線程。該線程結束後,會自動回收內存。(並不會開啟另一個進程); -
swap()
交換對象的線程。
std::jthread (C++20)
除了常用的std::thread
外,標準庫還存在着另一個可以創建線程的類,std::jthread
。他們之間的差別比較明顯的就是,std::jthread
會在解構的時候判斷線程是否還在運行joinable
,如果還在運行則自動調用request_stop
和join
。
除此之外,std::jthread
還提供了一個內置的std::stop_token
。可以通過線程函數的第一個參數來獲取(如果函數的第一個參數類型為std::stop_token
)。
可以通過get_stop_source
、get_stop_token
、request_stop
等方法來對其進行操作。
stop_token (C++20)
stop_token
類似於一個信號,告訴線程是否到了結束的時候。和stop_source
一起使用。stop_token
用來獲取是否退出(讀),而stop_source
用來請求推出(讀寫)。其方法:
-
request_stop
請求退出 -
stop_requested
獲取是否已經請求退出 -
stop_possible
獲取是否可以請求退出
樣例:
void thread_func(std::stop_token token) {
int data = 0;
while (!token.stop_requested()) {
printf("%d\n", data);
data++;
std::this_thread::sleep_for(1s);
}
printf("Exit\n");
}
int main() {
std::jthread mythread(thread_func);
std::this_thread::sleep_for(4s);
return 0;
}
輸出:
總結
本次講述了線程創建的一些方法,可以看到相比較C語言而言,由於C++11提出的函數對象(普通函數、匿名函數,std::bind
的輸出等)使得線程的創建更加的方便。
下一次將講述線程之間的通信。在C++中,線程之間的通信方法和C語言提供的類似,不過是將其包裝了一下。
Ref
[1] //www.zhihu.com/question/25532384