POSIX多线程笔记(1):pthread_detach与pthread_join的区别与应用

本文介绍了POSIX线程中pthread_detach和pthread_join的区别及应用场景。pthread_detach允许线程退出后资源自动回收,而pthread_join使调用线程等待指定线程完成并获取其返回值。通过多个实例分析,展示了未分离线程可能导致资源占用不释放的问题,强调了在多线程编程中合理使用这两个函数的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概念

POSIX线程的一个特点是:除非线程是被分离的了,否则在线程退出的时候,它的资源是不会被释放的。所以POSIX提供了pthread_detach函数用来分离线程:

int pthread_detach(pthread_t thread);

它设置线程的内部选项来说明线程退出后,其所占有的资源可以被回收。参数thread是要分离的线程的ID。

pthread_join函数可以使调用这个函数的线程等待指定的线程运行完成再继续执行。它的形式为:

int pthread_join(pthread_t thread, void ** value_ptr);

参数thread为要等待的线程的ID,参数value_ptr为指向返回值的指针提供一个位置,这参数thread为要等待的线程的ID,参数value_ptr为指向返回值的指针提供一个位置,这个返回值是由目标线程传递给pthread_exit或return的。

实例

例1
#include <unistd.h>
#include <semaphore.h>
#include <sys/types.h>
#include <dirent.h>
#include <pthread.h>
#include <errno.h>
#include <signal.h>
#include <time.h>
#include <stdio.h>
void * thread1(void *arg)
{
        int i;
        for (i=0 ; i < 5; i++)
        {
                usleep(500*1000);
                printf("thread1 running!\n");
        }
        printf("leave thread1!\n");
}
int main(int argc,char** argv)
{
        pthread_t tid;
        pthread_create(&tid, NULL, (void*)thread1, NULL);
        pthread_join(tid,NULL);
        printf("Leave main thread!\n");
        return 1;
}

运行结果:

在这里插入图片描述

例2
#include <unistd.h>
#include <semaphore.h>
#include <sys/types.h>
#include <dirent.h>
#include <pthread.h>
#include <errno.h>
#include <signal.h>
#include <time.h>
#include <stdio.h>
void * thread1(void *arg)
{
        int i;
        for (i=0 ; i < 5; i++)
        {
                usleep(500*1000);
                printf("thread1 running!\n");
        }
        printf("leave thread1!\n");
}
int main(int argc,char** argv)
{
        pthread_t tid;
        pthread_create(&tid, NULL, (void*)thread1, NULL);
        //pthread_join(tid,NULL);
        printf("Leave main thread!\n");
        return 0;
}

运行结果:

在这里插入图片描述

结果分析:

通过上面1和2两个例子可以发现在主进程中调用了pthread_join后,就必须等待子进程thread1运行结束以后才能接着往下执行。

例3
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <semaphore.h>
#include <sys/types.h>
#include <dirent.h>
#include <pthread.h>
#include <errno.h>
#include <signal.h>
#include <time.h>
#include <stdio.h>
void * thread(void *arg)
{
        int i = *((int*)arg);
        usleep(500*1000);
        printf("thread%d running!\n",i);
        return NULL;
}
int main(int argc,char** argv)
{
        pthread_t tid;
        int i = 0;
        while(1)
        {
                pthread_create(&tid, NULL, (void*)thread, &i);
                //pthread_join(tid,NULL);
                pthread_detach(tid);
                usleep(1000*1000);
                i++;
        }
        printf("Leave main thread!\n");
        return 0;
}

运行结果:

在当前命令窗口下会一直打印线程运行
在这里插入图片描述
然后我们用Xshell远程登录虚拟机,输入ps -ef查看运行程序的进程号,如图所示:
在这里插入图片描述
再输入top -d 1 -p XXXX(我这边是20302),可以看到在VIRT虚拟内存这一栏的数据一直在增大。
在这里插入图片描述

例4
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <semaphore.h>
#include <sys/types.h>
#include <dirent.h>
#include <pthread.h>
#include <errno.h>
#include <signal.h>
#include <time.h>
#include <stdio.h>
void * thread(void *arg)
{
        int i = *((int*)arg);
        usleep(500*1000);
        printf("thread%d running!\n",i);
        return NULL;
}
int main(int argc,char** argv)
{
        pthread_t tid;
        int i = 0;
        while(1)
        {
                pthread_create(&tid, NULL, (void*)thread, &i);
                //pthread_join(tid,NULL);
                pthread_detach(tid);
                usleep(1000*1000);
                i++;
        }
        printf("Leave main thread!\n");
        return 0;
}
运行结果:

在这里插入图片描述

结果分析:

在第3个例子中当前进程的VIRT(虚拟内存)会一直增大,而第4个例子中的VIRT保持在80424不变,这是因为在第3个例子中,创建一个完子线程以后,没有用 pthread_detach(tid) 把他设置为分离的,所以在子线程执行完以后,资源没有释放掉,等待主线程去读取状态,最后就造成了虚拟内存越来越大。

例5
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <semaphore.h>
#include <sys/types.h>
#include <dirent.h>
#include <pthread.h>
#include <errno.h>
#include <signal.h>
#include <time.h>
#include <stdio.h>
void * thread(void *arg)
{
        int i = *((int*)arg);
        usleep(500*1000);
        printf("thread%d running!\n",i);
        return NULL;
}
int main(int argc,char** argv)
{
        pthread_t tid;
        int i = 0;
        while(1)
        {
                pthread_create(&tid, NULL, (void*)thread, &i);
                pthread_join(tid,NULL);
                //pthread_detach(tid);
                usleep(1000*1000);
                i++;
        }
        printf("Leave main thread!\n");
        return 0;
}
运行结果:

在这里插入图片描述

结果分析:

在第5个例子中当前进程的VIRT(虚拟内存)还是不变,是因为主线程创建完一个子线程以后用pthread_join(tid,NULL); 进入阻塞状态,等待子线程运行结束后释放资源。而子线程运行到最后,因为有线程去读取他的状态,所以就不会出现例4中一直占用资源而不释放的情况。所以最后例5的结果和例4一样虚拟内存大小不变

总结

所以在我们的日常使用中,为了避免子线程运行结束但是占用资源不释放,可以使用pthread_detachpthread_join两个函数。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值