目录
pthread_cleanup_push、pthread_cleanup_pop
单个线程可以通过下列三种方式退出,在不终止这个进程的情况下停止他的控制流。
- 线程只是从启动例程中返回,返回值是线程的退出码。
- 线程可以被同一进程中的其他线程取消。
- 线程调用 pthread_exit。
#include<pthread.h>
void pthread_exit(void *rval_ptr);
rval_ptr 参数是一个指向线程退出状态值的指针。它的主要作用是允许线程在终止时向其创建者(通常是调用 pthread_join() 的线程)传递一个值,进程中其他线程可以通过调用pthread_join函数访问到这个指针,然后通过这个指针获取退出状态。
pthread_exit
#include<pthread.h>
void pthread_exit(void *rval_ptr);
pthread_exit 是 POSIX 线程库中显式终止线程的方法,想要结束的线程自己调用该函数。并将通过 rval_ptr 传递退出时想传递的值。
pthread_join
#include<pthread.h>
int pthread_join(pthread_t thread, void **rval_ptr);
pthread_join() 主要用于 线程同步 和 资源回收。它的核心功能是阻塞当前线程,直到目标线程终止,并获取目标线程的退出状态。
在默认情况下,线程的终止状态会保存到对该线程调用 pthread_join,如果线程已经处于分离状态,线程底层存储资源可以在线程终止时立即被回收,当线程被分离时,并不能用 pthread_join 函数等待它的终止状态。对分离的线程调用 pthread_join 会失败,返回 EINVAL。
pthread_join() 中的 rval_ptr 参数用于去传递目标线程的退出值。
void *worker(void *arg) {
int *result = malloc(sizeof(int));
*result = 42;
pthread_exit(result); // 传递退出状态
}
int main() {
pthread_t tid;
void *retval;
pthread_create(&tid, NULL, worker, NULL);
pthread_join(tid, &retval); // 阻塞等待
if (retval != NULL) {
printf("Result: %d\n", *(int*)retval);
free(retval); // 必须手动释放
}
}
运行结果:42
pthread_cancel
#include<pthread.h>
int pthread_cancel(pthread_t tid); //成功返回0,失败返回错误编号
pthread_cancel() 函数会使 tid 标识的线程如同调用了 PTHREAD_CANCELED 的 pthread_exit() 函数。这里要注意的是,pthread_cancel 并不等待线程终止,它仅仅提出请求,线程可以选择忽略取消方式或是控制取消方式。
pthread_cleanup_push、pthread_cleanup_pop
#include<pthread.h>
void pthread_cleanup_push(void (*rtn)(void*),void *arg);
void pthread_cleanup_pop(int execute);
线程可以在退出时调用想要调用的函数,主要用于在线程终止时自动释放资源(如锁、文件描述符等),这样的函数称为线程清理处理程序。线程可以建立多个清理处理程序。处理程序记录在栈中,也就是说它们的执行顺序与它们注册时的顺序相反。
pthread_cleanup_push()
将清理函数 rtn 压入线程的清理栈中,并绑定参数arg。清理函数会在以下情况被调用:
- 线程调用 pthread_exit() 显示终止
- 线程被其他线程取消(pthread_cancel)
- 调用 pthread_cleanup_pop(1) 主动触发
pthread_cleanup_pop()
将清理栈中弹出函数,并根据参数 execute 决定是否执行:
- execute != 0:执行清理函数
- execute == 0:仅弹出不执行
下面用一个例子来解释一下,例子是用于线程结束后调用清理函数自动释放内存。
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
/* 清理函数:释放内存 */
void cleanup(void *arg) {
printf("执行清理:释放内存 %p\n", arg);
free(arg);
}
void *thread_func(void *arg) {
int *data = malloc(sizeof(int));
*data = 42;
printf("线程分配内存: %p (值=%d)\n", data, *data);
/* 注册清理函数 */
pthread_cleanup_push(cleanup, data);
/* 模拟线程可能被取消的操作 */
if (1) { // 这里设为1只是为了演示,实际应该有条件判断
printf("线程调用pthread_exit退出\n");
pthread_exit(NULL); // 这会触发清理函数
}
/* 必须成对出现(实际不会执行到这里) */
pthread_cleanup_pop(0); // 0表示不执行清理(因为前面已经通过pthread_exit触发了)
return NULL;
}
int main() {
pthread_t tid;
pthread_create(&tid, NULL, thread_func, NULL);
pthread_join(tid, NULL);
printf("主线程结束\n");
return 0;
}
运行结果:线程分配内存: 0x7f8babc00000 (值=42)
线程调用pthread_exit退出
执行清理:释放内存 0x7f8babc00000
主线程结束

被折叠的 条评论
为什么被折叠?



