一、用一個初始函數創建一個線程
直接看代碼:注意c++在運行一個可執行程序的時候(創建了一個進程),會自動的創建一個主線程,這個主線程和進程同生共死,主線程結束,進程也就結束了。
1 #include "pch.h" 2 #include <iostream> 3 #include<thread> 4 void print1() 5 { 6 cout << "print1_1線程執行" << endl; 7 cout << "print1_2線程執行" << endl; 8 cout << "print1_3線程執行" << endl; 9 } 10 using namespace std; 11 int main() 12 { 13 thread mythread1(print1); 14 mythread1.join(); 15 //mythread1.detach(); 16 cout << "主線程執行" << endl; 17 return 0; 18 }
thread mythread1(print1)創建一個線程mythread1,print1()是該線程的初始函數(執行函數)。
mythread1.join();阻塞主線程,等待mythread1這個線程執行完畢在繼續執行,推薦這種做法。
mythread1.detach();分離,使主線程和線程mythread1分離,主線程可以先執行結束,如果主線程執行完了,子線程會在c++后台運行,一旦使用detach(),與這個子線程關聯的對象會失去對這個主線程的關聯,此時這個子線程會駐留在c++后台運行,當主線程執行完畢結束,子線程會移交給c++運行時庫管理,這個運行時庫會清理與這個線程相關的資源(守護線程),detach()會是子線程失去進程的控制,所以建議不要使用detach(),建議使用jion()。
return 0;表示主線程執行完畢,表明進程即將退出。
二、用類對象創建一個線程
直接看代碼:
1 #include "pch.h" 2 #include <iostream> 3 #include<thread> 4 class T 5 { 6 public: 7 /*情況一: 8 int ⁢//一個進程中的所有線程共享同一塊內存(內存共享),在線程中使用引用其實是不安全的 9 T(int &m_it) :it(m_it) 10 { 11 cout << "構造函數被執行" << endl; 12 } 13 */ 14 //不能用引用,應該像下面這樣用 15 int it; 16 T(int m_it) :it(m_it) 17 { 18 cout << "構造函數被執行" << endl; 19 } 20 T(const T &t) :it(t.it) { 21 cout << "拷貝構造函數被執行" << endl; 22 } 23 ~T() 24 { 25 cout << "析構函數被執行" << endl; 26 } 27 void operator()() 28 { 29 cout << "it值:" << it << endl; 30 } 31 }; 32 int main() 33 { 34 int itm = 8; 35 T t(itm);//調用了構造函數 36 thread mythread2(t); 37 mythread2.join(); 38 //mythread2.detach(); 39 cout << "主線程執行" << endl; 40 return 0; 41 }
thread mythread2(t);調用了拷貝構造函數
mythread2.detach();情況一的時候,這里絕對不能用detach(),因為類成員變量是一個引用,這里的itm等主線程執行完畢之后內存會回收,所以子線程打印的變量無效,這是一個重大的bug。一定要注意,最安全的做法就是直接使用值傳遞,生成一個副本,這樣使用detach()就不會有錯。
這里還有一個疑問?為什么使用detach(),主線程執行結束之后,用t這個局部對象沒有問題,t按理說會被系統回收之后就有問題了呀?
答:雖然t這個對象不在了(肯定會被回收),但是創建子線程的時候,這個對象t是被拷貝到子線程中去了的,所以用detach()而且主線程執行完畢后,子線程還是會繼續執行,這是沒有問題的.t被銷毀,但是被復制到線程中去的對象依然存在。
三、用lambda表達式創建一個線程
直接看代碼:
1 #include <iostream> 2 #include<thread> 3 using namespace std; 4 int main() 5 { 6 //用lambda表達式創建一個線程 7 auto mylamthread = [] {//這是一個lambda表達式 8 cout << "我的線程開始執行了" << endl; 9 //...... 10 cout << "我的線程執行結束了" << endl; 11 }; 12 thread mythread3(mylamthread); 13 mythread3.join(); 14 cout << "主線程執行結束" << endl; 15 return 0;//表示主線程執行結束,表明進程結束 16 }
四、認識一個函數
joinable(),這個函數用來判斷是否還可以使用join()和detach(),如果已經使用了join()或者detach(),則不能再使用detach()或者join()函數了,會返回一個布爾true,反之,返回一個false.