pthread_cleanup_push和pthread_clean_pop详解
时间: 2023-10-19 10:20:19 浏览: 196
`pthread_cleanup_push` 和 `pthread_cleanup_pop` 是 POSIX 线程库提供的两个函数,用于在线程退出时清理资源。
具体来说,当线程执行到 `pthread_cleanup_push` 函数时,它会将一个清理函数和一个参数压入线程的清理栈中。当线程退出时,无论是通过线程函数的 return 语句、pthread_exit 函数还是被取消,都会自动调用清理栈中的每个清理函数,并按照压入栈的顺序依次执行。
在多线程编程中,线程可能会因为各种原因(如出现异常)而异常终止,导致没有机会清理资源,从而造成资源泄漏或者其他问题。使用 `pthread_cleanup_push` 和 `pthread_cleanup_pop` 可以保证线程退出时一定会执行清理函数,避免这些问题。
下面是一个示例代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void cleanup_handler(void *arg) {
printf("cleanup: %s\n", (char *) arg);
}
void *thread_func(void *arg) {
char *msg = (char *) arg;
printf("thread: %s\n", msg);
// 压入清理函数
pthread_cleanup_push(cleanup_handler, "thread is finished");
// 执行任务
sleep(5);
// 弹出清理函数
pthread_cleanup_pop(1);
pthread_exit(NULL);
}
int main() {
pthread_t tid;
int ret;
ret = pthread_create(&tid, NULL, thread_func, "hello world");
if (ret != 0) {
fprintf(stderr, "pthread_create error\n");
exit(EXIT_FAILURE);
}
// 等待线程退出
ret = pthread_join(tid, NULL);
if (ret != 0) {
fprintf(stderr, "pthread_join error\n");
exit(EXIT_FAILURE);
}
printf("main: thread is finished\n");
return 0;
}
```
在这个示例中,线程执行到 `pthread_cleanup_push` 函数时,它会将 `cleanup_handler` 函数和字符串 `"thread is finished"` 压入清理栈中。当线程执行完任务后,无论是正常退出还是被取消,都会自动调用 `cleanup_handler` 函数,并打印出 `"cleanup: thread is finished"` 的消息。
需要注意的是,如果在 `pthread_cleanup_push` 和 `pthread_cleanup_pop` 之间调用了 `pthread_exit`,那么清理函数也会被执行。但是如果在 `pthread_cleanup_push` 和 `pthread_cleanup_pop` 之间调用了 `longjmp`,那么清理函数就不会被执行。因此,不要在使用 `setjmp` 和 `longjmp` 的代码中使用 `pthread_cleanup_push` 和 `pthread_cleanup_pop`。
阅读全文