加入式(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
请按任意键继续. . .
*/
虽然子线程sleep了一秒,但主线程在15行等到子线程结束了才继续往下执行。
t.join()的意思就是是主线程阻塞在这里,等待子线程t结束了才会继续往下执行,
分离式(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
请按任意键继续. . . threadRun
*/
主线程结束了,子线程才输出threadRun,还在执行,
16行t.detach()意思就是主线程和子线程t分离执行,互不影响。
注意:
启动线程后,你需要明确是要等待线程结束(加入式join),还是让其自主运行(分离式detach)。如果在 std::thread 对象销毁之后才决定(注意这里说的是std::thread 对象销毁之后,而不是子线程结束之后),会触发异常(std::thread 对象销毁时std::thread 的析构函数会调用 std::terminate(),这时再去决定会触发相应异常)
分离
如果想要分离一个线程,可以在线程启动后,直接使用detach()进行分离,但要保证线程结束之前,可访问的数据的有效性。
#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;
}
/*
请按任意键继续. . . 3134432 乱码
*/
13行向线程函数传入了temp的引用,但在线程函数内却输出乱码。由于14行使用了detach,两线程分离,test函数执行完时,会销毁局部变量temp,但线程函数还在运行,并通过temp的引用i访问了已经销毁的变量,所以尽量避免用一个能访问局部变量的函数去创建线程,除非十分确定线程会在函数完成前结束。
加入
如果打算等待对应线程,则需要细心挑选调用join()的位置,包括考虑如果出现异常了能否正确join(在异常处理过程中调用join())。
网友评论