1. 程式人生 > >c++11線程創建的三種方法

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

pch pan 銷毀 表達 tac 回收 系統 urn 執行

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

直接看代碼:註意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.

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