C++ 多线程join()和detach()的理解

C++ 多线程join()和detach()的理解

    • 问题产生原因
    • join
    • detch
    • 总结
    • 参考链接

问题产生原因

    每一个程序至少拥有一个线程,那就是执行main()函数的主线程,而多线程则是出现两个或两个以上的线程并行运行,即主线程和子线程在同一时间段同时运行。而在这个过程中会出现几种情况:

  • 主线程先运行结束
  • 子线程先运行结束
  • 主子线程同时结束

    在一些情况下需要在子线程结束后主线程才能结束,而一些情况则不需要等待,但需注意一点,并不是主线程结束了其他子线程就立即停止,其他子线程会进入后台运行.

join

join()函数是一个等待线程完成函数,主线程需要等待子线程运行结束了才可以结束:

#include 
#include 
using namespace std;

void func()
{
   for(int i = -10; i > -20; i--)
    {
        cout << "from func():" << i << endl;
    }
}

int main()			//主线程
{
	cout << "mian()" << endl;
    cout << "mian()" << endl;
    cout << "mian()" << endl;
	thread t(func);	//子线程
	t.join();		//等待子线程结束后才进入主线程
	return 0;
}

运行结果:
C++ 多线程join()和detach()的理解_第1张图片

detch

    称为分离线程函数,使用detach()函数会让线程在后台运行,即说明主线程不会等待子线程运行结束才结束。
    通常称分离线程为守护线程(daemon threads),UNIX中守护线程是指,没有任何显式的用户接口,并在后台运行的线程。这种线程的特点就是长时间运行;线程的生命周期可能会从某一个应用起始到结束,可能会在后台监视文件系统,还有可能对缓存进行清理,亦或对数据结构进行优化。另一方面,分离线程的另一方面只能确定线程什么时候结束,发后即忘(fire andforget)的任务就使用到线程的这种方式。
我们看下下面的这个例子:

#include 
#include 
#include 
void func(){
    for (int i = 0; i < 100; ++i) {
        std::cout<<"thread::func"<<std::endl;
    }
}
int main() {
    std::thread my_thread(func);
//    Sleep(1);
    my_thread.detach();
//    my_thread.join();
    return 0;
}

运行结果:
在这里插入图片描述
    由于使用的是detch函数,新线程与主线程分离,在detch函数执行完成,主线程main函数结束,my_thread对象销毁,还未执行一次打印线程也就结束了,这才造成这样的结果。下面我们加上Sleep(1);这句话,观察结果,验证我们的说法:
运行结果:
在这里插入图片描述
我们在执行线程分离前sleep1微秒,这样线程有机会完成几次打印,结果验证了前面的说法。
如果代码变成使用join函数

#include 
#include 
#include 
void func(){
    for (int i = 0; i < 100; ++i) {
        std::cout<<"thread::func"<<std::endl;
    }
}
int main() {
    std::thread my_thread(func);
//    Sleep(1);
//    my_thread.detach();
    my_thread.join();
    return 0;
}

结果:打印100次的thread::func。

总结

  • 在一个线程中,开了另一个线程去干另一件事,使用join函数后,原始线程会等待新线程执行结束之后,再去销毁线程对象。
  • 在一个线程中,开了另一个线程去干另一件事,使用join函数后,原始线程会等待新线程执行结束之后,再去销毁线程对象。
    这样有什么好处?---->因为它要等到新线程执行完,再销毁,线程对象,这样如果新线程使用了共享变量,等到新线程执行完再销毁这个线程对象,不会产生异常。如果不使用join,使用detch,那么新线程就会与原线程分离,如果原线程先执行完毕,销毁线程对象及局部变量,并且新线程有共享变量或引用之类,这样新线程可能使用的变量,就变成未定义,产生异常或不可预测的错误。
  • 所以,当你确定程序没有使用共享变量或引用之类的话,可以使用detch函数,分离线程。
  • 但是使用join可能会造成性能损失,因为原始线程要等待新线程的完成,所以有些情况(前提是你知道这种情况,如上)使用detch会更好。

参考链接

C++11多线程join()和detach()的理解
c++多线程编程:join()函数与detch()函数的区别

你可能感兴趣的:(C++)