第9章 线程编程(3)_线程清理和控制函数
3. 线程清理和控制函数
(1)线程清理函数,线程在退出时需要调用的函数,这与进程在退出时要用atexit注册的函数类似
(2)线程可以创建多个线理清理处理程序(thread cleanup handler)。这些处理程序记录在栈中,也就是执行顺序与它们注册的顺序相反。
|
头文件 |
#include <pthread.h> |
|
函数 |
void pthread_cleanup_push(void(*rtn)(void*), void* arg); void pthread_cleanup_pop(int execute); |
|
返回值 |
成功返回0,否则返回错误编号 |
|
参数 |
①rtn:清理函数指针 ②arg:调用清理函数传递的参数 ③execute:为1时表示执行线程清理函数,为0时不执行。 |
|
备注 |
①如果execute为0,清理函数将不被调用。 ②pthread_cleanup_pop将删除上次pthread_cleanup_push调用建立的清理处理程序。 ③pthread_cleanup_push和pthread_cleanup_pop是以宏方式实现的,pthread_cleanup_push()带有一个"{",而pthread_cleanup_pop()带有一个"}",因此这两个函数必须成对出现,且必须位于程序的同一级别的代码段中才能通过编译。 ④pthread_cleanup_push()的调用点到pthread_cleanup_pop()之间的程序段中的终止动作(包括调用 pthread_exit()和pthread_cancel)都将执行pthread_cleanup_push()所指定的清理函数。 |
(3)线程调用清理函数的时机
①调用pthread_exit;(注意,线程函数中调用return返回时,不会执行清理函数!)
②响应pthead_cancel的取消请求
③调用thread_cleanup_pop,并传入非0的execute参数。
【编程实验】线程清理函数
//pthread_clean.c
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
//定义线程清理函数
void clean_fun(void* arg)
{
char* s = (char*)arg;
printf("clean_fun: %s\n", s);
}
//线程函数
void* th_fun(void* arg)
{
pthread_cleanup_push(clean_fun, "first clean func");
pthread_cleanup_push(clean_fun, "second clean func");
printf("subthread(%lx) running\n", pthread_self());
//使用第1种传参方式:arg参数非0。
if(arg)
pthread_exit((void*)2); //触发调用清理函数并从这里返回,后面的
//代码将不被执行。
//if(arg)
// return ((void*)1); //return返回不会触发调用清理函数!
//注意,pthread_cleanup_pop必须与pthread_cleanup_pop成对出现!
//使用第2种传参方式时(arg==NULL).
//当使用该方式传参时,表示不希望执行清理函数,所以为pthread_cleanup_pop
//传入0,表示只是清除栈顶的清理函数,而不执行这个函数。
pthread_cleanup_pop(0); //后进先去:second
pthread_cleanup_pop(0); //first
return (void*)0;
}
int main(void)
{
int err = 0;
pthread_t th1, th2;
//创建子线程
if((err = pthread_create(&th1, NULL, th_fun, (void*)1))){
perror("pthread_create error");
}
pthread_join(th1, NULL);
printf("th1(%lx) finished!\n", th1);
if((err = pthread_create(&th2, NULL, th_fun, (void*)0))){
perror("pthread_create error");
}
pthread_join(th2, NULL);
printf("th2(%lx) finished!\n", th2);
return 0;
}
/*输出结果:
[root@bogon]# bin/pthread_clean
subthread(b77d0b70) running //线程1,调用了清理函数
clean_fun: second clean func //并且以后进先出的方式调用
clean_fun: first clean func
th1(b77d0b70) finished!
subthread(b77d0b70) running //线程2:不会调用清理函数
th2(b77d0b70) finished!
*/
4. 进程、线程启动和终止方式的比较
|
进程 |
线程 |
描述 |
|
fork() |
pthread_create() |
创建新的控制流 |
|
return/exit()/_exit() |
return/pthread_exit() |
从现有控制流中退出 |
|
wait() |
pthread_join() |
从控制流中得到退出状态 |
|
getpid |
pthread_self() |
获取控制流ID |
|
atexit() |
pthread_cleanup_push() pthread_cleanup_pop(); |
注册在退出控制流时调用的函数。 |
|
abort |
pthread_cancel |
请求控制流的非正常退出 |
|
【备注】在默认情况下,线程的终止状态会保存到对该线程调用pthread_join,如果线程己经处于分离 状态,线程的终止状态信息可以在线程终止时立即被回收。调用pthread_detach可以使线程进入分离状态。 |
||

浙公网安备 33010602011771号