07LinuxC线程学习之pthread_exit函数和总结exit、return、pthread_exit,pthread_cancel各自退出效果和join,detach的作用

1 pthread_exit函数

void pthread_exit(void *retval);	
/*
	功能:退出当前子线程。与在某个函数中返回区别一下。
	参1:retval表示线程退出状态,通常传NULL。
*/

2 exit的作用

1)测试1
下面的程序和结果可以看到,当执行到第二个线程时,我们调用了exit(0),导致后面3,4,5线程没有打印。也就是说,该函数会将整个进程退出,无论在哪个线程中。

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int func(int a){
    exit(0);
}

void *tfn(void *arg){
    int i;

    i = (int)arg;
    sleep(i);
    if (i == 2){
    	func(8888);//测试1
    	//return NULL;//测试2
    	//func(8888);//测试3
    }

    printf("I'm %dth thread, Thread_ID = %lu\n", i+1, pthread_self());

    pthread_exit(NULL);
}

int main(int argc, char *argv[]){
    int n = 5, i;
    pthread_t tid[n];
	for (i = 0; i < n; i++) {
        tid[i] = -1;
    }
    
    for (i = 0; i < n; i++) {
        pthread_create(&tid[i], NULL, tfn, (void *)i);
    }
	
	//为了方便观察,不回收
	//for (i = 0; i < n; i++) {
        //pthread_join(tid, NULL);
    //}    

    printf("I am main, and I am not a process, I'm a thread!\n" 
            "main_thread_ID = %lu\n", pthread_self());

    return 0;
}

程序结果:
在这里插入图片描述

3 return的作用

1)测试2
同样的代码,我们将func函数中的exit改成return NULL,可以看到结果1能够依次打印。
结果1:
在这里插入图片描述
2)测试3
然后再将return NULL封装一下放在一个新的函数func中返回,重新调用func,可以看到结果2,我们想要退出线程3,但却没有退出。

void* func(){
	return NULL;
}

结果2:
在这里插入图片描述

  • 所以可以总结到return的作用是:返回到调用者处。有可能会退出进程(放在主线程时),有可能会退出线程,也有可能什么也不退出。

3 pthread_exit的作用

将测试3的代码改成下面,可以看到结果,线程3退出了。所以pthread_exit的作用是只退出当前子线程,记住是只。即使你放在主线程,它也会只退出主线程,其它线程有运行的仍会继续运行。

void* func(){
	pthread_exit(NULL);
}

结果:
在这里插入图片描述

所以我们可以大总结这些退出函数的作用了。

4 总结exit、return、pthread_exit,pthread_cancel各自退出效果和pthread_join,pthread_detach的作用

  • 1)return:返回到调用者那里去。注意,在主线程退出时效果与exit,_exit一样。即return有可能会退出进程(放在主线程时),有可能会退出线程,也有可能什么也不退出。
  • 2)pthread_exit():只退出当前子线程。注意:在主线程退出时,其它线程不会结束。同样可以执行。所以这个只字非常重要。并且,与return一样,pthread_exit退出的线程也需要调用pthread_join去回收子线程的资源(8k左右),否则服务器长时间运行会浪费资源导致无法再创建新线程。
  • 3)exit,_exit: 将进程退出,无论哪个子线程调用整个程序都将结束。
  • 4)pthread_join():阻塞等待回收子线程。
  • 5)pthread_cancel():可以杀死子线程,但必须需要一个契机,这个契机就是系统调用。一般方法是调用pthread_testcancel提供契机处理。并且join再回收该被杀死的子线程的返回值为pthread.h中的宏#define PTHREAD_CANCELED ((void *) -1)。
  • 6)pthread_detach:1)注意,所有线程的错误号返回都只能使用strerror这个函数判断,不能使用perror,因为perror是调用进程的全局错误号,不适合单独线程的错误分析,所以只能使用strerror。2)线程可以被置为detach状态,这样的线程一旦终止就立刻回收它占用的所有资源,而不保留终止状态。不能对一个已经处于detach状态的线程调用pthread_join,这样的调用将返回EINVAL错误。也就是说,如果已经对一个线程调用了pthread_detach就不能再调用pthread_join了。
  • 9
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
pthread_exit函数的返回值类型是void,而不是int。它用于退出当前子线程,并且可以传递一个指针作为线程退出状态。通常情况下,我们会将该参数设置为NULL。\[1\] 该函数作用退出当前线程,而不是整个进程。与在某个函数返回不同,pthread_exit函数只会终止当前线程,而不会影响其他线程的执行。\[1\] 在你提供的代码exit(0)函数被调用,这会导致整个进程退出,而不仅仅是当前线程。因此,后面的线程没有打印出来。\[3\] #### 引用[.reference_title] - *1* *3* [07LinuxC线程学习之pthread_exit函数总结exitreturn、pthread_exit,pthread_cancel各自退出效果join...](https://blog.csdn.net/weixin_44517656/article/details/112253724)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Linux多线程编程(pthread_creat、pthread_exit、pthread_join、pthread_detach)](https://blog.csdn.net/weixin_42934918/article/details/114363789)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值