加入式(join):
#include<thread>
#include<iostream>
#include <windows.h>
void myPrintf() {
Sleep(1000);
std::cout << "threadRun" << std::endl;
return;
}
int main()
{
std::thread t(myPrintf);
t.join(); //15
std::cout << "main" << std::endl;
system("pause");
return 0;
}
/*輸出:
threadRun
main
請(qǐng)按任意鍵繼續(xù). . .
*/
雖然子線程sleep了一秒励背,但主線程在15行等到子線程結(jié)束了才繼續(xù)往下執(zhí)行春霍。
t.join()的意思就是是主線程阻塞在這里,等待子線程t結(jié)束了才會(huì)繼續(xù)往下執(zhí)行叶眉,
分離式(detach):
#include<thread>
#include<iostream>
#include <windows.h>
void myPrintf() {
Sleep(1000);
std::cout << "threadRun" << std::endl;
return;
}
int main()
{
std::thread t(myPrintf);
t.detach(); //16
std::cout << "main" << std::endl;
system("pause");
return 0;
}
/*輸出:
main
請(qǐng)按任意鍵繼續(xù). . . threadRun
*/
主線程結(jié)束了址儒,子線程才輸出threadRun芹枷,還在執(zhí)行,
16行t.detach()意思就是主線程和子線程t分離執(zhí)行莲趣,互不影響鸳慈。
注意:
啟動(dòng)線程后,你需要明確是要等待線程結(jié)束(加入式j(luò)oin)妖爷,還是讓其自主運(yùn)行(分離式detach)蝶涩。如果在 std::thread 對(duì)象銷毀之后才決定(注意這里說(shuō)的是std::thread 對(duì)象銷毀之后,而不是子線程結(jié)束之后)絮识,會(huì)觸發(fā)異常(std::thread 對(duì)象銷毀時(shí)std::thread 的析構(gòu)函數(shù)會(huì)調(diào)用 std::terminate()绿聘,這時(shí)再去決定會(huì)觸發(fā)相應(yīng)異常)
分離
如果想要分離一個(gè)線程,可以在線程啟動(dòng)后次舌,直接使用detach()進(jìn)行分離熄攘,但要保證線程結(jié)束之前,可訪問(wèn)的數(shù)據(jù)的有效性彼念。
#include<thread>
#include<iostream>
#include<windows.h>
void fun(int & i) {
Sleep(1000);
std::cout << i << std::endl;
return;
}
void test() {
int temp = 2;
std::thread t(fun,std::ref(temp)); //13
t.detach(); //14
}
int main()
{
test();
system("pause");
return 0;
}
/*
請(qǐng)按任意鍵繼續(xù). . . 3134432 亂碼
*/
13行向線程函數(shù)傳入了temp的引用挪圾,但在線程函數(shù)內(nèi)卻輸出亂碼。由于14行使用了detach逐沙,兩線程分離哲思,test函數(shù)執(zhí)行完時(shí),會(huì)銷毀局部變量temp吩案,但線程函數(shù)還在運(yùn)行棚赔,并通過(guò)temp的引用i訪問(wèn)了已經(jīng)銷毀的變量,所以盡量避免用一個(gè)能訪問(wèn)局部變量的函數(shù)去創(chuàng)建線程徘郭,除非十分確定線程會(huì)在函數(shù)完成前結(jié)束靠益。
加入
如果打算等待對(duì)應(yīng)線程,則需要細(xì)心挑選調(diào)用join()的位置残揉,包括考慮如果出現(xiàn)異常了能否正確join(在異常處理過(guò)程中調(diào)用join())胧后。