在前文讨论了线程创建的一些基本东西,这里讨论有哪些方法可以使线程终止,线程终止又是如何与创建所需的参数进行关联的。
一,正常终止
线程在执行完成之后,正常终止。
二,线程取消
2.1 线程取消的定义
一般情况下,线程在其主体函数退出的时候会自动终止,但同时也可以因为接收到另一个线程发来的终止(取消)请求而强制终止。
2.2 线程取消的语义
线程取消的方法是向目标线程发Cancel信号,但如何处理Cancel信号则由目标线程自己决定,或者忽略、或者立即终止、或者继续运行至Cancelation-point(取消点),由不同的Cancelation状态决定。线程接收到CANCEL信号的缺省处理(即pthread_create()创建线程的缺省状态)是继续运行至取消点,也就是说设置一个CANCELED状态,线程继续运行,只有运行至Cancelation-point的时候才会退出。
2.3 取消点
根据POSIX标准,pthread_join()、pthread_testcancel()、pthread_cond_wait()、
pthread_cond_timedwait()、sem_wait()、sigwait()等函数以及read()、write()等会引起阻塞的系统调用都是Cancelation-point,而其他pthread函数都不会引起Cancelation动作。但是pthread_cancel的手册页声称,由于LinuxThread库与C库结合得不好,因而目前C库函数都不是Cancelation-point;但CANCEL信号会使线程从阻塞的系统调用中退出,并置EINTR错误码,因此可以在需要作为Cancelation-point的系统调用前后调用
pthread_testcancel(),从而达到POSIX标准所要求的目标,即如下代码段:
- <span style="font-size:18px;">pthread_testcancel();
- retcode = read(fd, buffer, length);
- pthread_testcancel();</span>
2.4 程序设计方面的考虑
如果线程处于无限循环中,且循环体内没有执行至取消点的必然路径,则线程无法由外部其他线程的取消请求而终止。因此在这样的循环体的必经路径上应该加入pthread_testcancel()调用。
2.5 与线程取消相关的pthread函数
int pthread_cancel(pthread_t
thread)
发送终止信号给thread线程,如果成功则返回0,否则为非0值。发送成功并不意味着thread会终止。
int
pthread_setcancelstate(int state, int
*oldstate)
设置本线程对Cancel信号的反应,state有两种值:PTHREAD_CANCEL_ENABLE(缺省)和
PTHREAD_CANCEL_DISABLE,分别表示收到信号后设为CANCLED状态和忽略CANCEL信号继续运行;old_state如果不为
NULL则存入原来的Cancel状态以便恢复。
int pthread_setcanceltype(int type, int
*oldtype)
设置本线程取消动作的执行时机,type由两种取值:PTHREAD_CANCEL_DEFFERED和
PTHREAD_CANCEL_ASYCHRONOUS,仅当Cancel状态为Enable时有效,分别表示收到信号后继续运行至下一个取消点再退出和立即执行取消动作(退出);oldtype如果不为NULL则存入运来的取消动作类型值。
void
pthread_testcancel(void)
检查本线程是否处于Canceld状态,如果是,则进行取消动作,否则直接返回。
三,pthread_exit
在线程内显示的调用,以终止线程。
四,等待终止
在一个线程里面,我们要等待另一个线程结束。可以通过调用pthread_join函数。
- <span style="font-size:18px;">pthread_join (pthread_t thread, void** threadreturn);</span>
这将会在调用线程引起阻塞,并且在创建thread所指定的线程时,其分离属性必须是pthread_create_joinable.否则调用出错。