一、线程清理函数
#include <pthread.h>
void ptread_clean_push(void (*rtn) (void *), void *arg); 注册清理函数,押栈
void ptread_clean_pop(int excute); 清理函数,出栈
分析:这两个函数是成对出现的,少一个会导致编译不通过
参数详解:
- pthread_cleanup_push:该函数的第一个参数是清理函数,参数是void*,返回值是void类型的,第二个函数是押栈需要传的参数。
- pthread_cleanup_pop:出栈,调用清理函数,其中只有一个参数,该参数是非零会响应清理函数,是0的话,不做处理
注意该处理函数是被放在栈区,所以先进栈的后出栈,也就是说先进栈的函数,最后被调用。
当有以下三种操作的时候会调用清理函数:
- 调用pthread_exit()函数,会响应清理处理函数。
- 用非零的函数调用pthread_cleanup_pop()函数。
- 响应取消请求。
二、程序清单
测试代码:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
void *first_cleanup(void *arg)
{
printf("this is clenup function %s\n", arg);
}
void *second_cleanup(void *arg)
{
printf("this is clenup function %s\n", arg);
}
void *thread_fun1(void *arg)
{
sleep(1);
printf("this is thread 1\n");
pthread_cleanup_push(&first_cleanup, "thread 1");
pthread_cleanup_push(&second_cleanup, "thread 1");
pthread_cleanup_pop(1);
pthread_cleanup_pop(1);
return (void*)0;
}
void *thread_fun2(void *arg)
{
sleep(2);
printf("this is thread 2\n");
pthread_cleanup_push(&first_cleanup, "thread 2");
pthread_cleanup_push(&second_cleanup, "thread 2");
pthread_exit((void*)0);
pthread_cleanup_pop(0);
pthread_cleanup_pop(0);
}
void *thread_fun3(void *arg)
{
sleep(3);
printf("this is thread 3\n");
pthread_cleanup_push(&first_cleanup, "thread 3");
pthread_cleanup_push(&second_cleanup, "thread 3");
pthread_cleanup_pop(0);
pthread_cleanup_pop(0);
pthread_exit((void*)0);
}
int main()
{
pthread_t tid1, tid2, tid3;
pthread_create(&tid1, NULL, thread_fun1, NULL);
pthread_create(&tid2, NULL, thread_fun2, NULL);
pthread_create(&tid3, NULL, thread_fun3, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
pthread_join(tid3, NULL);
return 0;
}
输出结果:
分析:pthread_cleanup_pop()中参数是非0时会调用清理处理函数,当参数是0的时候,pthread_cleanup_pop该函数的参数在pthread_exit()退出前调用无论是0还是非0,都会响应清理处理函数,但是pthread_exit()在pthread_cleanup_pop函数之后调用,pthread_cleanup_pop函数的参数是0的话,清理函数已经退出,所以就不会再调用到清理处理函数了。
三、参考资料
1. 线程的清理处理程序