C/C++:pthread_join()和pthread_detach()的区别
简单来说:pthread_detach()和pthread_join()就是控制子线程回收资源的两种不同的方式。同一进程间的线程具有共享和独立的资源,其中共享的资源有堆、全局变量、静态变量、文件等公用资源。而独享的资源有栈和寄存器,这两种方式就是决定子线程结束时如何回收独享的资源。
pthread_detach()即主线程与子线程分离,两者相互不干涉,子线程结束同时子线程的资源自动回收。pthread_join()即是子线程合入主线程,主线程会一直阻塞,直到子线程执行结束,然后回收子线程资源,并继续执行。
代码编译过程为(文件取名main.cc)
/** 编译 -lpthread为链接pthread**/g++ -o a.out main.cc -lpthread/** 执行 **/./a.out
linux下内存占用查看指令为
/** 先找到想要查看的程序的进程号 **/ps -ef/** -d 1 表示数据刷新频率1秒 -p xxx 表示想查看的程序的进程号 **/top -d 1 -p xxx
测试程序如下
// for test#include <iostream>#include <unistd.h>#include <pthread.h> using namespace std;void* svc(void* args){ sleep(3); cout << "111111111111111" << endl; return nullptr;}int main(){ do { pthread_t threadId = 0; const int ret = pthread_create(&threadId, 0, &svc, nullptr); if (ret == -1) { cout << "error while create thread!" << endl; return 0; } sleep(1)// pthread_join(threadId, nullptr);// cout << "222222222222222" << endl;// pthread_detach(threadId);// cout << "333333333333333" << endl; }while (false); getchar(); return 0;}
先注销掉pthread_join()和pthread_detach()两个函数,代码中每隔1s创建一个子线程,并且子线程在执行结束后资源并没有被释放,变成了僵尸线程,此时用top明明查看进程的内存占用,发现进程占用的内存不断增大。此时若取消注释pthread_join()或者是pthread_detach()中的任意一个,再重新编译并启动程序,发现进程内存占用不会增大。因为子线程资源被释放掉了(无论是子线程自动释放还是主线程回收,都是释放)。
然后在一个子线程中观察两种释放的区别(此时不再创建多个子线程)
// for test#include <iostream>#include <unistd.h>#include <pthread.h> using namespace std;void* svc(void* args){ sleep(3); cout << "111111111111111" << endl; return nullptr;}int main(){ do { pthread_t threadId = 0; const int ret = pthread_create(&threadId, 0, &svc, nullptr); if (ret == -1) { cout << "error while create thread!" << endl; return 0; } sleep(1) pthread_join(threadId, nullptr); cout << "222222222222222" << endl;// pthread_detach(threadId);// cout << "222222222222222" << endl; } while (false);// getchar(); return 0;}
主线程调用pthread_join()时,主线程将阻塞在这条调用语句上,不再执行下面的cout,直到子线程执行完毕后,主线程回收了子线程的资源,才会继续向下执行。这段代码的测试结果是
先输出子线程休眠三秒后打印的111111111111111,后输出pthread_join()语句之后的222222222222222,这样我们发现,在子线程执行完毕之后,主线程才继续执行pthread_join()之后的语句。而如果我们使用pthread_detach(),代码如下
// for test#include <iostream>#include <unistd.h>#include <pthread.h> using namespace std;void* svc(void* args){ sleep(3); cout << "111111111111111" << endl; return nullptr;}int main(){ do { pthread_t threadId = 0; const int ret = pthread_create(&threadId, 0, &svc, nullptr); if (ret == -1) { cout << "error while create thread!" << endl; return 0; } sleep(1)// pthread_join(threadId, nullptr);// cout << "222222222222222" << endl; pthread_detach(threadId); cout << "222222222222222" << endl; } while (false);// getchar(); return 0;}
结果如下
主线程不会等待子线程执行结束就已经执行结束了,因此子线程根本就没有来得及执行,程序就结束了。
我觉得这里可以理解为如果子线程的资源需要主线程来回收的话,那么主线程就一定要等子线程结束,因为子线程还没用完呢你就不能拿去回收,但是如果子线程资源要自动回收的话,那么主线程就不必等你了。