linux线程的取消(终止)方法
关键:
pthread_cancel函数发送终止信号
pthread_setcancelstate函数设置终止方式
pthread_testcancel函数取消线程(另一功能是:设置取消点)
1线程取消的定义
一般情况下,线程在其主体函数退出的时候会自动终止,但同时也可以因为接收到另一个线程发来的终止(取消)请求而强制终止。
2线程取消的语义
线程取消的方法是向目标线程发Cancel信号(pthread_cancel函数发送Cancel信号),但如何处理Cancel信号则由目标线程自己决定,或者忽略、或者立即终止、或者继续运行至Cancelation-point(取消点),由不同的Cancelation状态(pthread_setcancelstate函数设置状态)决定。
线程接收到CANCEL信号的缺省处理(即pthread_create()创建线程的缺省状态)是继续运行至取消点,也就是说设置一个CANCELED状态,线程继续运行,只有运行至Cancelation-point的时候才会退出。
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标准所要求的目标,即如下代码段:
pthread_testcancel();
retcode=read(fd,buffer,length);
pthread_testcancel();
4程序设计方面的考虑
如果线程处于无限循环中,且循环体内没有执行至取消点的必然路径,则线程无法由外部其他线程的取消请求而终止。因此在这样的循环体的必经路径上应该加入pthread_testcancel()调用。
5与线程取消相关的pthread函数
intpthread_cancel(pthread_tthread)
发送终止信号给thread线程,如果成功则返回0,否则为非0值。发送成功并不意味着thread会终止。
intpthread_setcancelstate(intstate,int*oldstate)
设置本线程对Cancel信号的反应,state有两种值:PTHREAD_CANCEL_ENABLE(缺省)和PTHREAD_CANCEL_DISABLE,分别表示收到信号后设为CANCLED状态和忽略CANCEL信号继续运行;old_state如果不为NULL则存入原来的Cancel状态以便恢复。
intpthread_setcanceltype(inttype,int*oldtype)
设置本线程取消动作的执行时机,type由两种取值:PTHREAD_CANCEL_DEFFERED和PTHREAD_CANCEL_ASYCHRONOUS,仅当Cancel状态为Enable时有效,分别表示收到信号后继续运行至下一个取消点再退出和立即执行取消动作(退出);oldtype如果不为NULL则存入运来的取消动作类型值。
voidpthread_testcancel(void)
功能一:设置取消点;
功能二:检查本线程是否处于Canceld状态,如果是,则进行取消动作,否则直接返回。
代码:
#include<stdio.h> #include<errno.h> #include<unistd.h> #include<stdlib.h> #include<pthread.h> #defineTHREAD_MAX4 pthread_mutex_tmutex; pthread_tthread[THREAD_MAX]; staticinttries; staticintstarted; voidprint_it(int*arg) { pthread_ttid; tid=pthread_self(); printf("Thread%lxwascanceledonits%dtry.\n",tid,*arg); } void*Search_Num(intarg) { pthread_ttid; intnum; intk=0,h=0,j; intntries; tid=pthread_self(); /*while(pthread_mutex_trylock(&mutex)==EBUSY) { printf("**************busy****************\n"); pthread_testcancel(); }*/ srand(arg); num=rand()&0xFFFFFF; //pthread_mutex_unlock(&mutex); printf("threadnum%lx\n",tid); ntries=0; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL); pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL); pthread_cleanup_push((void*)print_it,(void*)&ntries); while(1) { num=(num+1)&0xffffff; ntries++; if(arg==num) { //只允许一个线程操作此处 while(pthread_mutex_trylock(&mutex)==EBUSY){ //一个线程操作后其余线程进入次循环挂起,等待pthread_cancel函数发送cancel信号终止线程 k++; if(k==10000) { printf("----------2busy2-----------\n"); } pthread_testcancel(); } tries=ntries; //pthread_mutex_unlock(&mutex);//如果加上这句话,将会有好几个线程找到主函数中设定的值pid printf("Thread%lxfoundthenumber!\n",tid); for(j=0;j<THREAD_MAX;j++) { if(thread[j]!=tid) { pthread_cancel(thread[j]); } } break; } if(ntries%100==0) { h++; /*线程阻塞,其他线程争夺资源,或者是等待pthread_cancel函数发送cancel信号终止线程*/ pthread_testcancel(); /*这是为了弄明白pthread_testcancel函数的作用而设置的代码段*/ if(h==10000) { h=0; printf("----------threadnum%lx-------------\n",tid); } } } pthread_cleanup_pop(0); return(void*)0; } intmain() { inti,pid; pid=getpid();//设置要查找的数 pthread_mutex_init(&mutex,NULL); printf("Searchthenumof%d\n",pid); for(started=0;started<THREAD_MAX;started++) { pthread_create(&thread[started],NULL,(void*)Search_Num,(void*)pid); } for(i=0;i<THREAD_MAX;i++) { printf("-----------i=%d--------------\n",i); pthread_join(thread[i],NULL); } printf("Ittook%dtriesotfindthenumber!\n",tries); return0; }
运行结果:
Searchthenumof6531 -----------i=0-------------- threadnumb6fbcb70 threadnumb67bbb70 threadnumb5fbab70 threadnumb77bdb70 ----------threadnumb67bbb70------------- Threadb67bbb70foundthenumber! ----------threadnumb6fbcb70------------- ----------threadnumb77bdb70------------- ----------2busy2----------- ----------threadnumb5fbab70------------- ----------2busy2----------- Threadb5fbab70wascanceledonits1174527try. Threadb77bdb70wascanceledonits1023100try. -----------i=1-------------- Threadb6fbcb70wascanceledonits1174527try. -----------i=2-------------- -----------i=3-------------- Ittook1174527triesotfindthenumber!
从这结果里你有没有看出什么呢?呵呵~.~
以上就是小编为大家带来的linux线程的取消(终止)方法全部内容了,希望大家多多支持毛票票~