1

加入式(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())。


趣燃
5 声望0 粉丝