线程之线程终止


如果进程中的任一线程调用了exit、_Exit或者_exit,那么整个进程就会终止。与此类似,如果信号的默认动作是终止进程,那么,把该信号发送到线程会终止整个进程。

单个线程可以通过下列三种方式退出,在不终止整个进程的情况下停止它的控制流。

(1)线程只是从启动例程中返回,返回值是线程的退出码。

(2)线程可以被同一进程中的其他线程取消。

(3)线程调用pthread_exit。

#include <pthread.h>
 pthread_exit( *rval_ptr);

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

#include <pthread.h>
 pthread_join(pthread_t thread,  **

调用线程将一直阻塞,直到指定的线程调用pthread_exit、从启动例程中返回或者被取消。如果线程只是从它的启动例程返回,rval_ptr将包含返回码。如果线程被取消,由rval_ptr指定的内存单元就置为PTHREAD_CANCELED。

可以通过调用pthread_join自动把线程置于分离状态,这样资源就可以恢复。如果线程已经处于分离状态,pthread_join调用就会失败,返回EINVAL。

如果对线程的返回值并不感兴趣,可以把rval_ptr置为NULL。在这种情况下,调用pthread_join函数将等待指定的线程终止,但并不获取线程的终止状态。

实例

程序清单11-2说明了如何获取已终止的线程的退出码。

程序清单11-2 获得线程退出状态

#include <pthread.h>

 * *(( *) * * *)        *= pthread_create(&(err != = pthread_create(&(err != = pthread_join(tid1, &(err != , (= pthread_join(tid2, &(err != , (

运行程序清单11-2中的程序,得到的结果是:

<pthread.h> *s, foo *, fp->, fp->, fp->, fp-> * * foo foo = {, , , , & *)&, & * * *) foo *= pthread_create(&(err != = pthread_join(tid1, ( *)&(err != sleep(

运行程序清单11-3中的程序得到:

情况一:把带注释的行去掉注释也编译进程序中时的运行结果:

foo foo = {, , ,

#include <pthread.h>

在默认情况下,pthread_cancel函数会使得由tid标识的线程的行为表现为如同调用了参数为PTHREAD_CANCELED的pthread_exit函数,但是,线程可以选择忽略取消方式或是控制取消方式。注意,pthread_cancel并不等待线程终止,它仅仅提出请求。

线程可以安排它退出时需要调用的函数,这与进程可以用atexit函数安排进程退出时需要调用的函数是类似的。这样的函数称为线程清理处理程序(thread cleanup handler)。线程可以建立多个清理处理程序。处理程序记录在栈中,也就是说它们的执行顺序与它们注册时的顺序相反。

#include <pthread.h>
 pthread_cleanup_push( (*rtn)( *),  * pthread_cleanup_pop( execute);

当线程执行以下动作时调用清理函数(调用参数为arg,清理函数rtn的调用顺序是由pthread_cleanup_push函数来安排的):

  • 调用pthread_exit时。
  • 相应取消请求时。
  • 用非零execute参数调用pthread_cleanup_pop时。

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

这些函数有一个限制,由于它们可以实现为宏,所以必须在与线程相同的作用域中以匹配对的形式使用,pthread_cleanup_push的宏定义可以包含字符{,在这种情况下对应的匹配字符}就要在pthread_cleanup_pop定义中出现。

实例

程序清单11-4显示了如何使用线程清理处理程序。需要把pthread_cleanup_pop调用和pthread_cleanup_push调用匹配起来,否则,程序编译可能通不过。

程序清单11-4 线程清理处理程序

#include <pthread.h>

 *, ( * * *(( *)(( *) * * *) *)        *= pthread_create(&tid1, NULL, thr_fn1, ( *)(err != = pthread_create(&tid2, NULL, thr_fn2, ( *)(err != = pthread_join(tid1, &(err != , (= pthread_join(tid2, &(err != , (

运行程序清单11-4中的程序会得到:

本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/

相关内容