C++:多线程中的小白(2)线程启动、结束、创建线程、join、detach
目錄
?
一、范例演示:線程運(yùn)行的開始和結(jié)束
二、其他創(chuàng)建線程的手法
一、范例演示:線程運(yùn)行的開始和結(jié)束
(1)thrad
(2)join()函數(shù)
(3)detach()函數(shù)
(4)joinable()函數(shù)
?
二、其他創(chuàng)建線程的手法
(1)用類,以及一個(gè)問題范例
(2)用lambda表達(dá)式
-----------------------------------正題----------------------------
假如我們有一個(gè)最簡(jiǎn)單的main函數(shù):(用它來演示線程運(yùn)行的開始和結(jié)束)
int main()
{cout<<"I love you"<<endl;//實(shí)際上這個(gè)是主線程在執(zhí)行,主線程從main函數(shù)返回,則整個(gè)進(jìn)程執(zhí)行完畢。return 0;
}
//該程序運(yùn)行起來生成一個(gè)進(jìn)程,該進(jìn)程所屬的主線程開始自動(dòng)運(yùn)行起來。(當(dāng)主線程執(zhí)行完了之后就等于整個(gè)進(jìn)程執(zhí)行完畢了)
下面我們自己創(chuàng)建一個(gè)線程:(說明程序運(yùn)行起來之后我們會(huì)有兩個(gè)線程,相當(dāng)于我們這個(gè)程序有兩條線,兩條平行線在跑;
主線程從main函數(shù)開始執(zhí)行,我們自己創(chuàng)建的另外一個(gè)線程也需要從一個(gè)函數(shù)開始執(zhí)行(有時(shí)候我們也稱這個(gè)函數(shù)為初始函數(shù)),一旦這個(gè)函數(shù)運(yùn)行完畢就代表這我們這個(gè)線程運(yùn)行結(jié)束;)
PS:整個(gè)進(jìn)程是否執(zhí)行完畢的標(biāo)志是什么?主線程是否執(zhí)行完,如果主線程執(zhí)行完畢了,那么代表著整個(gè)進(jìn)程就執(zhí)行完畢了;此時(shí),一般情況下如果其他子線程還沒有執(zhí)行完畢,那么這些子線程也會(huì)被操作系統(tǒng)強(qiáng)行終止(因?yàn)槲艺麄€(gè)進(jìn)程都沒了),所以一般情況下我們得到一個(gè)結(jié)論:如果大家想保持子線程(此處的子線程是我們自己用代碼創(chuàng)建的線程)的運(yùn)行狀態(tài)(意思就是想讓子線程運(yùn)行),那么大家就要讓主線程一直保持運(yùn)行,不要讓主線程運(yùn)行完畢(主線程運(yùn)行完畢的標(biāo)志就是執(zhí)行完return 0;這個(gè)語句,就退出了,整個(gè)進(jìn)程就退出了)。但是這條規(guī)律也有例外的。
thread:是標(biāo)準(zhǔn)庫(kù)中的一個(gè)類,這個(gè)類就是用來創(chuàng)建線程的。
創(chuàng)建線程的步驟:
- 包含一個(gè)頭文件:include<stread>
- 要?jiǎng)?chuàng)建一個(gè)函數(shù)(因?yàn)橹吧线呎f過子線程也是從函數(shù)開始的)。
所以在上述基礎(chǔ)上,先創(chuàng)建一個(gè)函數(shù):
//自己創(chuàng)建的函數(shù)也要從一個(gè)函數(shù)(初始函數(shù))開始運(yùn)行
void myprint()
{cout<<"我的線程開始執(zhí)行了"<<endl;//.....干其他事cout<<“我的線程執(zhí)行完畢了”<<endl;
}
int main()
{//在main中開始寫代碼,開啟線程,thread是一個(gè)類,定義一個(gè)thread類的對(duì)象mytobj,然后我傳進(jìn)去構(gòu)造函數(shù)的參數(shù),我的參數(shù)直接傳進(jìn)入一個(gè)myprint(myprint是個(gè)函數(shù),函數(shù)也是一個(gè)可調(diào)用對(duì)象),std::thread mytobj(myprint);//生成了一個(gè)屬于thread類的對(duì)象。//myprint構(gòu)造函數(shù)的實(shí)參,實(shí)際上是一個(gè)可調(diào)用對(duì)象(也就是說這個(gè)thread里邊的形參接收的是一個(gè)可調(diào)用對(duì)象)//1這句代碼的作用是:(1)創(chuàng)建出來了另外一條線,也就是創(chuàng)建了線程,這個(gè)線程執(zhí)行的起點(diǎn)(入口)是myprint;(2)這個(gè)線程(函數(shù))myprint開始執(zhí)行 mytobj.join();//這個(gè)對(duì)象mytobj調(diào)用一個(gè)方法join()//2作用:阻塞主線程,并等待myprint()子線程執(zhí)行完,因?yàn)閙yobj代表的是myprint這個(gè)子線程。
//上邊兩行就是創(chuàng)建一個(gè)線程并且開始執(zhí)行cout<<"I love China"<<endl;//3當(dāng)子線程執(zhí)行完畢,再往下走,執(zhí)行該語句的輸出,最終return 0;程序結(jié)束,主線程退出了。return 0;
}
結(jié)果展示如下:
??兩條平行線一起走。
因?yàn)橹骶€程執(zhí)行的是return 0;子線程只要從上到下把這個(gè)子線程的初始函數(shù)myprint里邊的代碼都執(zhí)行完畢,這個(gè)子線程他自動(dòng)就會(huì)執(zhí)行完了。?
通過觀察結(jié)果我們可以看到,是線程先執(zhí)行,I love china是后執(zhí)行,兩條線走但是輸出順序是先是線程cout里邊的信息,然后才是主線程main函數(shù)中的cout內(nèi)容,最后整個(gè)程序或者說是進(jìn)程運(yùn)行結(jié)束。(必須明確一下:現(xiàn)在這個(gè)代碼是有兩條線路的,有兩個(gè)線程在跑,相當(dāng)于整個(gè)程序的執(zhí)行有兩條線,在同時(shí)走,所以這個(gè)程序可以同時(shí)干兩個(gè)事,即使一條線被堵住了,另外一條線還是可以通行的,這就是多線程。(即使主線程被堵住了,那我子線程不耽誤我走;比如以網(wǎng)沒有使用多線程的時(shí)候,是從main函數(shù)開始執(zhí)行的,如果我調(diào)用了其他函數(shù),我流程就走到其他函數(shù)里邊去了,然后執(zhí)行完其他函數(shù)流程再回來,一條流程。但是現(xiàn)在不是一條流程,現(xiàn)在是兩條流程在走。))
?
join()函數(shù):
join的中文意思是加入?yún)⒓?#xff0c;說白了就是阻塞。阻塞主線程,主線程是main函數(shù)代表的這個(gè)東西,main函數(shù)代表的執(zhí)行的這條線。該函數(shù)作用:阻塞主線程讓主線程等待子線程執(zhí)行完畢,然后子線程和主線程匯合,然后主線程在mytobj.join();就開始等待,然后主線程再往下走。(意思就是剛開始兩條線路一起走,當(dāng)主線程遇到j(luò)oin函數(shù)的時(shí)候主線程就明白了我們程序開發(fā)者希望主線程等待子線程,這個(gè)時(shí)候主線程阻塞在這里,等待myprint()代表的子線程執(zhí)行完,當(dāng)子線程執(zhí)行完畢,這個(gè)join()就執(zhí)行完畢,那么阻塞的這個(gè)join就繼續(xù)往下走,也就是子線程的執(zhí)行流程跟咱們當(dāng)前的主線程匯合了(所以說白了這個(gè)join就是阻塞等待子線程執(zhí)行完))所以join函數(shù)非常重要,決定這個(gè)整個(gè)程序的執(zhí)行循序,主線程等待子線程,這是一種等待,等待匯合之后共同結(jié)束這個(gè)程序。
假如上邊把join這行注釋掉,不等待子線程了,結(jié)果如下(程序報(bào)異常了,并且輸出是混亂的):
為什么會(huì)發(fā)生異常?
子線程我剛打印一條,我還沒打印第二條呢,主線程已經(jīng)執(zhí)行完畢了,這時(shí)我的子線程還沒有執(zhí)行完畢呢,(意思就是我子線程還在進(jìn)行時(shí),你主線程已經(jīng)return 0;了,那這個(gè)程序就整個(gè)退出了,退出就導(dǎo)致異常。)所以結(jié)論,如果你子線程沒執(zhí)行完,你主線程提前執(zhí)行完了,那你這樣的程序員是不合格的,寫出來的程序也是不穩(wěn)定的。
一個(gè)書寫良好的程序應(yīng)該是主線程等待子線程執(zhí)行完畢后自己才能最終退出。
detach():
主線程可不可以不等待子線程執(zhí)行完,自己先執(zhí)行完呢?可以的。這就是上邊說的例外。
傳統(tǒng)多線程:主線程要等待子線程執(zhí)行完畢,然后自己再最后退出。
打破傳統(tǒng)的寫法就是detach()。
detach():中文分離的意思。意思就是主線程我不和你子線程匯合了,你子線程執(zhí)行你的我主線程執(zhí)行我的,你主線程也不必等我了子線程運(yùn)行結(jié)束了,你可以先行結(jié)束,這并不影響我子線程的執(zhí)行。這就是detach()函數(shù)的作用。
引入detach()的原因:
比如說我們創(chuàng)建了很多的子線程,讓主線程逐個(gè)等待子線程結(jié)束,這種編程方法不太好,所以引入了detach()。
個(gè)人建議還是采用join()這種方式,意思就是就算你子線程很多,但是我挨個(gè)等你,因?yàn)橹挥械冗@種方式,我子線程都安全退出了,這才是一種最穩(wěn)定最好的編程方法。
一旦detach()之后,與這個(gè)主線程關(guān)聯(lián)的thread對(duì)象,就這個(gè)mytobj就會(huì)失去與主線程的關(guān)聯(lián),此時(shí)這個(gè)子線程myprint這個(gè)線程就會(huì)駐留在后臺(tái)運(yùn)行了,(這個(gè)后臺(tái)咱們就看不見摸不著了,主線程跟該子線程失去聯(lián)系)這個(gè)子線程就相當(dāng)于被C++運(yùn)行時(shí)庫(kù)接管了(運(yùn)行時(shí)庫(kù)就是系統(tǒng)這玩意,不用管他,自會(huì)有人幫我們?nèi)ジ?#xff09;,當(dāng)這個(gè)子線程執(zhí)行完成后,由運(yùn)行時(shí)庫(kù)負(fù)責(zé)清理該線程相關(guān)的資源(主要包括變量?jī)?nèi)存釋放等)
將上述的代碼用detach替換join。
//自己創(chuàng)建的函數(shù)也要從一個(gè)函數(shù)(初始函數(shù))開始運(yùn)行
void myprint()
{cout<<"我的線程開始執(zhí)行了"<<endl;//.....干其他事cout<<“我的線程執(zhí)行完畢了1”<<endl;cout<<“我的線程執(zhí)行完畢了2”<<endl;cout<<“我的線程執(zhí)行完畢了3”<<endl;cout<<“我的線程執(zhí)行完畢了4”<<endl;cout<<“我的線程執(zhí)行完畢了5”<<endl;cout<<“我的線程執(zhí)行完畢了6”<<endl;cout<<“我的線程執(zhí)行完畢了7”<<endl;cout<<“我的線程執(zhí)行完畢了8”<<endl;cout<<“我的線程執(zhí)行完畢了9”<<endl;cout<<“我的線程執(zhí)行完畢了10”<<endl;
}
int main()
{//在main中開始寫代碼,開啟線程,thread是一個(gè)類,定義一個(gè)thread類的對(duì)象mytobj,然后我傳進(jìn)去構(gòu)造函數(shù)的參數(shù),我的參數(shù)直接傳進(jìn)入一個(gè)myprint(myprint是個(gè)函數(shù),函數(shù)也是一個(gè)可調(diào)用對(duì)象),std::thread mytobj(myprint);//生成了一個(gè)屬于thread類的對(duì)象。//myprint構(gòu)造函數(shù)的實(shí)參,實(shí)際上是一個(gè)可調(diào)用對(duì)象(也就是說這個(gè)thread里邊的形參接收的是一個(gè)可調(diào)用對(duì)象)//1這句代碼的作用是:(1)創(chuàng)建出來了另外一條線,也就是創(chuàng)建了線程,這個(gè)線程執(zhí)行的起點(diǎn)(入口)是myprint;(2)這個(gè)線程(函數(shù))myprint開始執(zhí)行 mytobj.detach();cout<<"我的線程開始執(zhí)行了主線程收尾,最終最線程安全正常退出!"<<endl;//3當(dāng)子線程執(zhí)行完畢,再往下走,執(zhí)行該語句的輸出,最終return 0;程序結(jié)束,主線程退出了。return 0;
}
結(jié)果展示:
結(jié)果只打印主線程中的一條,子線程中的一個(gè)都沒打印。進(jìn)程就退出了,進(jìn)程退出表明我們這個(gè)線程執(zhí)行完了,
把上述代碼再改一下:
//自己創(chuàng)建的函數(shù)也要從一個(gè)函數(shù)(初始函數(shù))開始運(yùn)行
void myprint()
{cout<<"我的線程開始執(zhí)行了"<<endl;//.....干其他事cout<<“我的線程執(zhí)行完畢了1”<<endl;cout<<“我的線程執(zhí)行完畢了2”<<endl;cout<<“我的線程執(zhí)行完畢了3”<<endl;cout<<“我的線程執(zhí)行完畢了4”<<endl;cout<<“我的線程執(zhí)行完畢了5”<<endl;cout<<“我的線程執(zhí)行完畢了6”<<endl;cout<<“我的線程執(zhí)行完畢了7”<<endl;cout<<“我的線程執(zhí)行完畢了8”<<endl;cout<<“我的線程執(zhí)行完畢了9”<<endl;cout<<“我的線程執(zhí)行完畢了10”<<endl;
}
int main()
{//在main中開始寫代碼,開啟線程,thread是一個(gè)類,定義一個(gè)thread類的對(duì)象mytobj,然后我傳進(jìn)去構(gòu)造函數(shù)的參數(shù),我的參數(shù)直接傳進(jìn)入一個(gè)myprint(myprint是個(gè)函數(shù),函數(shù)也是一個(gè)可調(diào)用對(duì)象),std::thread mytobj(myprint);//生成了一個(gè)屬于thread類的對(duì)象。//myprint構(gòu)造函數(shù)的實(shí)參,實(shí)際上是一個(gè)可調(diào)用對(duì)象(也就是說這個(gè)thread里邊的形參接收的是一個(gè)可調(diào)用對(duì)象)//1這句代碼的作用是:(1)創(chuàng)建出來了另外一條線,也就是創(chuàng)建了線程,這個(gè)線程執(zhí)行的起點(diǎn)(入口)是myprint;(2)這個(gè)線程(函數(shù))myprint開始執(zhí)行 mytobj.detach();//這個(gè)后邊不能再用join函數(shù)了。cout<<"I Love China1"<<endl;cout<<"I Love China2"<<endl;cout<<"I Love China3"<<endl;cout<<"I Love China4"<<endl;cout<<"I Love China5"<<endl;return 0;
}
運(yùn)行結(jié)果
因?yàn)楝F(xiàn)在detach了,我主線程走我主線程的,子線程走我子線程的,我兩條路咱倆自己執(zhí)行各自的誰也別耽誤誰。
如果你再執(zhí)行一次,你發(fā)現(xiàn)輸出結(jié)果又不一樣了。
主線程執(zhí)行完I Love china 5之后主線程就退出了,退出去之后導(dǎo)致本來主線程如果不退出之后,子線程會(huì)把cout的所有語句輸出,但是我們卻發(fā)現(xiàn)主線程一旦退出,子線程就輸出不出來了,(也就是78910語句還沒來得及輸出到屏幕呢,主線程執(zhí)行到return 0了,執(zhí)行完return 0主線程就退出了,那整個(gè)進(jìn)程就退出了,進(jìn)程退出之后子線程后邊的就輸出不到屏幕上來了,因?yàn)槟氵@個(gè)東西使用了detach你被C++運(yùn)行時(shí)庫(kù)接管了),所以只要主線程一結(jié)束,你子線程顯示的內(nèi)容就輸出不到屏幕上來了。(detach因?yàn)橹骶€程退出了,導(dǎo)致子線程的輸出就中斷了,隨著主線程的退出,整個(gè)進(jìn)程的退出,這個(gè)線程也轉(zhuǎn)入到后臺(tái)去執(zhí)行了,本來他就是在后臺(tái)執(zhí)行的,因?yàn)槟銖膁etach的那一時(shí)刻起,整個(gè)線程就是在后臺(tái)執(zhí)行的,只不過是你進(jìn)程沒執(zhí)行完,我線程可以通過輸出語句往你屏幕上打印輸出信息罷了,你一旦進(jìn)程退出了,你就沒有辦法在屏幕上再打印出信息來而已,你就看不到后續(xù)的myprint打印出來的信息,所以detach這個(gè)感覺就是detach會(huì)導(dǎo)致這個(gè)線程myprint失去咱們的控制,我們管不了它了,所以通常情況下更推薦用join等待的方法,這個(gè)主線程等子線程;當(dāng)然這個(gè)不是絕對(duì)的,如果子線程要干的活和這個(gè)主線程沒有什么關(guān)系,大家其實(shí)是可以使用detach的,注意,你一旦調(diào)用detach了,那么這個(gè)線程myprint就跑到后臺(tái)去了,你就管不著它了,那你也不能再join回來了,就不能說再用join了,后邊不能再調(diào)用join這個(gè)函數(shù)了(一旦detach就不能再用join否則系統(tǒng)會(huì)報(bào)異常)。)
joinable()
joinable函數(shù)功能:判斷是否可以成功使用join()或者detach(),返回true(表示可以join或者可以detach)或者false(不能join或者不可以detach),因我們?cè)趧?chuàng)建完線程后要么使用join要么使用detach,那么我們有可能中途需要判斷哪一個(gè)地方能不能使用join或者detach,這個(gè)時(shí)候我們就用到j(luò)oinable了,因?yàn)橐院髮憦?fù)雜代碼得時(shí)候可能會(huì)需要判斷是否join過或者是否detach過等等,這個(gè)函數(shù)就發(fā)揮作用了。比如下邊:
//自己創(chuàng)建的函數(shù)也要從一個(gè)函數(shù)(初始函數(shù))開始運(yùn)行
void myprint()
{cout<<"我的線程開始執(zhí)行了"<<endl;//.....干其他事cout<<“我的線程執(zhí)行完畢了”<<endl;
}
int main()
{std::thread mytobj(myprint);//mytobj.joinable();//此處調(diào)用joinable()函數(shù)返回的就是true。//因?yàn)橹挥袆?chuàng)建線程這一行,還沒有調(diào)用過join和detach。//所以使用一個(gè)if語句進(jìn)行判斷:if(mytobj.joinable()){cout<<"1:joinable()==true"<<endl;}//因?yàn)橹挥袆?chuàng)建線程這一行,還沒有調(diào)用過join和detach,If語句里邊就可以join()或者detach();elae{cout<<"1:joinable()==false"<<endl;}mytobj.join();//mytobi.joinable()//此處調(diào)用joinable()函數(shù)返回的就是false。因?yàn)榍斑呉呀?jīng)調(diào)用過join函數(shù)了if(mytobj.joinable()){cout<<"2:joinable()==true"<<endl;}elae{cout<<"2:joinable()==false"<<endl;}//此處已經(jīng)調(diào)用過了join()函數(shù)了。cout<<"I love China"<<endl;return 0;
}
總結(jié):你detach后不能再detach或者join了;同樣你join之后也不能再join或者detach了。
二、其他創(chuàng)建線程的手法
上述創(chuàng)建線程是從一個(gè)函數(shù)他是可調(diào)用對(duì)象創(chuàng)建一個(gè)線程,然后這個(gè)線程就從myprint函數(shù)作為入口點(diǎn),開始執(zhí)行。之前講過thread這個(gè)東西是接受一個(gè)可調(diào)用對(duì)象作為參數(shù),來創(chuàng)建線程的,那函數(shù)它是一個(gè)可調(diào)用對(duì)象,但是還有其他可調(diào)用對(duì)象啊。
(1)用類對(duì)象作為一個(gè)可調(diào)用對(duì)象
首先得定義一個(gè)類。(如果一個(gè)類作為可調(diào)用對(duì)象的話,那么我們這個(gè)類中必須得有public,)
這個(gè)類就是一個(gè)可調(diào)用對(duì)象,如果用這個(gè)類去創(chuàng)建線程的話,那么這個(gè)線程的執(zhí)行入口點(diǎn)應(yīng)該就是operator這個(gè)函數(shù)了
//創(chuàng)建一個(gè)類
class TA
{
public:void operator()();//重載括號(hào),第二個(gè)()里邊是參數(shù),這里先不帶參數(shù){cout<<"我的線程operator()開始執(zhí)行了"<<endl;//..執(zhí)行其他事cout<<"我的線程operator()結(jié)束執(zhí)行了"<<endl;}//沒有這個(gè)圓括號(hào)重載的函數(shù),那么改類就不是一個(gè)可調(diào)用對(duì)象
}
int main()
{TA ta;//首先生成一個(gè)類對(duì)象,(最好不要使用匿名對(duì)象,如果使用匿名對(duì)象下邊應(yīng)該傳入的是TA(),沒試過不知道對(duì)不對(duì))thread mytobj2(ta);//ta是個(gè)可調(diào)用對(duì)象(上一個(gè)例子傳入的是函數(shù),現(xiàn)在是類對(duì)象)mytobj2.join();//等待子線程執(zhí)行結(jié)束cout<<"I Love China"<<endl;return 0;
}
結(jié)果:
給該類增加一個(gè)構(gòu)造函數(shù):
//創(chuàng)建一個(gè)類
class TA
{
public:int &m_i;//定義成員變量,為int,但是它是一個(gè)引用//TA(int &i);//構(gòu)造函數(shù),參數(shù)是引用TA(int &i):m_i(i){}//構(gòu)造函數(shù)帶參數(shù)void operator()();//重載括號(hào),第二個(gè)()里邊是參數(shù),這里先不帶參數(shù){cout<<"m_i1的值為:"<<m_i<<endl;//..執(zhí)行其他事cout<<"m_i2的值為"<<m_i<<endl;cout<<"m_i3的值為"<<m_i<<endl;cout<<"m_i4的值為"<<m_i<<endl;}//沒有這個(gè)圓括號(hào)重載的函數(shù),那么改類就不是一個(gè)可調(diào)用對(duì)象
}
int main()
{int myi=6;TA ta(myi);//這樣才能創(chuàng)建ta這個(gè)對(duì)象thread mytobj3(ta);//ta是被賦值的,相當(dāng)于又生成一個(gè)新對(duì)象復(fù)制到這個(gè)線程中去的//ta是個(gè)可調(diào)用對(duì)象(上一個(gè)例子傳入的是函數(shù),現(xiàn)在是類對(duì)象)mytobj3.detach();//等待子線程執(zhí)行結(jié)束cout<<"I Love China"<<endl;return 0;
}
該結(jié)果每次執(zhí)行結(jié)果不一樣。
假設(shè)這個(gè)主線程他先執(zhí)行完,也能是子線程后執(zhí)行完的,那如果主線程先執(zhí)行完了,你子線程后執(zhí)行完的,如果出現(xiàn)這個(gè)情況的話,主線程執(zhí)行完了,子線程還在后臺(tái)執(zhí)行這呢,但是不要忘記,我這個(gè)子線程打印的m_i他是一個(gè)引用,它綁著的是i,這個(gè)i綁著的是myi,myi他是主線程的局部變量,當(dāng)主線程執(zhí)行結(jié)束后,myi變量的內(nèi)存就已經(jīng)被回收了,被銷毀了,那你主線程執(zhí)行完,那你這個(gè)myi就被銷毀了,這段內(nèi)存被回收了,那你子線程沒執(zhí)行完,仍然在打印這段內(nèi)存的內(nèi)容(被回收的這段內(nèi)存的內(nèi)容),那么就會(huì)產(chǎn)生不可預(yù)料的結(jié)果了,所以最好join等子線程執(zhí)行完成。(假設(shè)主線程運(yùn)行結(jié)束,那么我這個(gè)ta他也是一個(gè)局部變量,我們用局部對(duì)象構(gòu)造一個(gè)線程,那我這個(gè)主線程執(zhí)行完了,那我這個(gè)ta不就無效了嗎?如果ta無效的話,那還能執(zhí)行這個(gè)ta里邊的可調(diào)用圓括號(hào)不就不能執(zhí)行了嗎?但是為什么這里用ta沒問題?還有一個(gè)問題,一旦調(diào)用了detach()那我主線程執(zhí)行結(jié)束了,我這里用的ta這個(gè)對(duì)象還在嗎?這個(gè)對(duì)象你一旦主線程結(jié)束了,這個(gè)ta對(duì)象肯定是不在了,因?yàn)橹骶€程結(jié)束了嘛,他是個(gè)局部變量嘛,此時(shí)這個(gè)對(duì)象不在了,如果這個(gè)對(duì)象不在了還能調(diào)用這個(gè)對(duì)象的成員函數(shù)嗎?答:因?yàn)檫@個(gè)對(duì)象實(shí)際上是被復(fù)制到線程中去的,執(zhí)行完主線程后ta會(huì)被銷毀,但是所復(fù)制的ta對(duì)象依舊存在,所以只要你這個(gè)TA類對(duì)象里沒有引用,沒有指針,那么就不會(huì)產(chǎn)生問題,因?yàn)槟氵@個(gè)對(duì)象是被復(fù)制到線程中去的,)
(2)用lambda表達(dá)式創(chuàng)建
int main()
{auto mylamthread=[]{//這個(gè)就是線程入口cout<<"我的線程3開始執(zhí)行了"<<endl;//...干其他事cout<<"我的線程3執(zhí)行結(jié)束了"<<endl;};thread mytobj4(mylamthread);//mylamthread是個(gè)可調(diào)用對(duì)象mytobj4.join();cout<<"I Love China"<<endl;return 0;
}
執(zhí)行結(jié)果:
?
總結(jié)
以上是生活随笔為你收集整理的C++:多线程中的小白(2)线程启动、结束、创建线程、join、detach的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PCL调错:(3)error C2589
- 下一篇: Eigen:C++中Eigen库的安装与