c++11線程創建的三種方法


一、用一個初始函數創建一個線程

直接看代碼:注意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 &it;//一個進程中的所有線程共享同一塊內存(內存共享),在線程中使用引用其實是不安全的
 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.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM