线程的终止

2014-09-26 18:39:39   最后更新: 2014-09-29 13:03:26   访问数量:1151




如果线程调用 _exit、exit 或 _Exit 函数中的某个,则整个进程都会被终止,同样,对于用来终止进程的信号,如果执行其默认动作,则整个进程也会被终止

如果想要结束单个进程,有下列三种方法:

  1. 线程从启动函数中返回
  2. 线程可以被同一进程中的其他线程取消
  3. 线程调用 pthread_exit 可以主动退出

 

pthread_exit

void pthread_exit(void *rval_ptr);

 

定义于 pthread.h 中

 

rval_ptr 是一个无类型指针,与传给启动例程的单个参数类似,同一进程中的其他线程可以通过 pthread_join 函数访问这个指针

 

pthread_join

int pthread_join(pthread_t thread, void **rval_ptr);

 

定义于 pthread.h 中

调用成功返回0,否则返回错误编号

 

调用该函数的线程将一直阻塞,直到参数中指定的线程调用 pthread_exit 函数退出

 

需要注意的是,pthread_exit 要返回全局结构体变量或者malloc函数分配结构,如果返回局部变量,则栈可能会被其他线程覆盖

 

线程可以请求取消同一进程中的其他线程

int pthread_cancle(pthread_t tid);

 

定义于 pthread.h 中

若成功则返回0,否则返回错误编号

 

在默认情况下,pthread_cancle 函数会使由 tid 标识的线程的行为表现为如同调用了参数为 PTHREAD_CANCLE 的 pthread_exit 函数

线程也可以选择忽略或控制取消方式

线程可以安排在他退出时需要调用的函数,和进程调用 atexit 函数安排进程退出时需要调用的函数类似

下面的程序就是线程清理处理程序,处理程序记录在栈中,因此,它们的执行顺序与注册顺序相反

void pthread_cleanup_push(void (*rfn)(void *), void *arg); void pthread_cleanup_pop(int execute);

 

当下列情况时,会调用清理函数:

  • 调用 pthread_exit 退出
  • 响应取消请求
  • 用非0的execute参数调用pthread_cleanup_pop

 

不过 execute 参数如果被设置为0,则不会调用清理函数,不过无论哪种情况,由于 pthread_cleanup_pop 函数的调用,都将删除上次 pthread_cleanup_push 调用建立的清理处理程序

下面的例子展示了线程的清理和处理:

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <pthread.h> void cleanup(void *arg) { printf("cleanup: %s\n", (char *)arg); } void *thr_fn1(void *arg) { printf("thread 1 start\n"); pthread_cleanup_push(cleanup, "thread 1 first handler"); pthread_cleanup_push(cleanup, "thread 1 second handler"); printf("thread 1 push complete\n"); if (arg) return (void *)1; pthread_cleanup_pop(0); pthread_cleanup_pop(0); return (void *)1; } void *thr_fn2(void *arg) { printf("thread 2 start\n"); pthread_cleanup_push(cleanup, "thread 2 first handler"); pthread_cleanup_push(cleanup, "thread 2 second handler"); printf("thread 2 push complete\n"); if (arg) pthread_exit((void *)2); pthread_cleanup_pop(0); pthread_cleanup_pop(0); pthread_exit((void *)2); } int main() { int err; void *tret; pthread_t tid1, tid2; err = pthread_create(&tid1, NULL, thr_fn1, (void *)1); if (err != 0) { printf("cannot create thread 1: %s\n", strerror(err)); exit(-1); } err = pthread_create(&tid2, NULL, thr_fn2, (void *)1); if (err != 0) { printf("cannot create thread 2: %s\n", strerror(err)); exit(-1); } err = pthread_join(tid1, &tret); if (err != 0) { printf("cannot join with thread 1: %s\n", strerror(err)); exit(-1); } printf("thread 1 exit code %d\n", (int)tret); err = pthread_join(tid2, &tret); if (err != 0) { printf("cannot join with thread 2: %s\n", strerror(err)); exit(-1); } printf("thread 2 exit code %d\n", (int)tret); return 0; }

 

程序执行结果如下:

 

从结果中可以看出,两个线程都已经正确启动和退出,但是只有第二个线程的清理出里程序被调用

程序说明如下:

  1. 如果从线程中正常return,而不是调用 pthread_exit 函数退出,则不会进行线程清理工作
  2. 清理处理程序的调用顺序与注册顺序相反
  3. execute 参数如果被设置为0 也会调用清理函数(这是为什么呢?)

 

在默认情况下,线程的终止状态会一直保存到对该线程调用 pthread_join,除非线程已经处于分离状态

处于分离状态的线程在终止时资源会被立即回收

线程可以通过调用 pthread_detach 使线程处于分离状态

int pthread_detach(pthread_t tid);

 

如若调用成功则会返回0,否则返回错误编号

 






读书笔记      技术帖      linux      unix      龙潭书斋      apue      unix环境高级编程      进程      线程      thread      pthread      pthread_exit     


京ICP备15018585号