作者:曹忠明,华清远见嵌入式学院讲师。
上次说了如何去创建一个线程及如何向线程中传递一个参数那么这次我们说一下如何终止一个线程。
如进程中调用exit,_exit使进程结束一样,线程也可以通过类似的方法结束。
一、线程的执行体结束线程自然结束。
二、可以通过调用pthread_exit使程序结束。
pthread_exit 的原型为:
void pthread_exit(void *value_ptr);
value_ptr是一个无类型返回值,其他线程可以通过调用phread_join来获得这个值。
phread_join 的原型为:
int pthread_join(pthread_t thread, void **value_ptr);
调用pthread_join可以等待线程thread的退出并获得退出时的状态,如果不关心线程返回值的话,value_ptr可以置为NULL,下面我们用一个例程说明这两个函数的使用方法。
#include <stdio.h>
#include <pthread.h>
void *thread_a(void *arg)
{
printf("thread 1 enter\n");
pthread_exit((void *)1);
}
void *thread_b(void *arg)
{
printf("thread 2 enter\n");
pthread_exit((void *)2);
}
int main(int argc, char **argv)
{
pthread_t tid_a,tid_b;
int err;
void *value_ptr;
err = pthread_create(&tid_a,NULL,thread_a,NULL);
if(err < 0)
{
perror("pthread_create thread_a");
}
err = pthread_create(&tid_b,NULL,thread_b,NULL);
if(err < 0)
{
perror("pthread_create thread_a");
}
pthread_join(tid_b,&value_ptr);
printf("phtread %d exit!\n",(int)value_ptr);
pthread_join(tid_a,&value_ptr);
printf("phtread %d exit!\n",(int)value_ptr);
sleep(5);
printf("the main close\n");
return 0;
}
三、被统一线程中的其他线程取消而结束。
线程可以通过调用pthread_cancel函数向同一进程中的其他线程发送取消的信号,但是这个先好的响应可以设定,可以设置为立即终止或忽略。所以发送取消信号并不意味着线程就会终止。
与线程取消相关的函数有:
phtread_cancel原型为:
int pthread_cancel(pthread_t thread);
这个函数向线程thread发送终止信号。
pthread_setcancelstate原型为:
int pthread_setcancelstate(int state, int *oldstate);
这个函数设定线程接收到终止信号的反应,state有两种值:PHTREAD_CANCEL_ENABLE(默认为这个状态)和PHREAD_CANCEL_DISABLE,这两个值分别代表接受掉终止信号终止线程和或略这个信号。oldstate用来存放线程原来的状态用来以后恢复只用,如不用回复可以设置为NULL。
pthread_setcanceltype原型为:
int pthread_setcanceltype(int type, int *oldtype);
这个函数用来设定线程接收到终止信号的执行时间,type也是有两个值:PTHREAD_CANCEL_DEFFERED和PTHREAD_CANCEL_ASYCHRONOUS,这两个值分别表示线程接收到终止信号是运行到下一个取消点退出还是立即退出。同样oldtype也是用来存放线程原来的状态。
pthread_testcancel原型为:
void pthread_testcancel(void);
检查线程是否处于canceld状态如果是则执行取消动作否则立即返回。
下面用一个例程说明这几个函数的使用。
#include <stdio.h>
#include <pthread.h>
void *thread_a(void *arg)
{
if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL) != 0)
{
perror("setcancelstate");
}
if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL) != 0)
{
perror("setcancelsype");
}
while(1)
{
sleep(1);
printf("thread_a\n");
pthread_testcancel();
}
}
void *thread_b(void *arg)
{
if(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL) != 0)
{
perror("setcancelstate");
}
while(1)
{
sleep(1);
printf("thread_b\n");
pthread_testcancel();
}
}
void *thread_c(void *arg)
{
if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL) != 0)
{
perror("setcancelstate");
}
if(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL) != 0)
{
perror("setcancelsype");
}
while(1)
{
sleep(1);
printf("thread_c\n");
pthread_testcancel();
}
}
int main(int argc, char **argv)
{
pthread_t tid_a,tid_b,tid_c;
int err;
err = pthread_create(&tid_a,NULL,thread_a,(void *)&tid_a);
if(err < 0)
{
perror("pthread_create thread_a");
}
printf("create tid_a = %u\n",tid_a);
err = pthread_create(&tid_b,NULL,thread_b,(void *)&tid_b);
if(err < 0)
{
perror("pthread_create thread_b");
}
printf("create tid_b = %u\n",tid_b);
err = pthread_create(&tid_c,NULL,thread_c,(void *)&tid_c);
if(err < 0)
{
perror("pthread_create thread_c");
}
printf("create tid_c = %u\n",tid_c);
sleep(5);
if(pthread_cancel(tid_a) != 0)
{
perror("pthread_cancel tid_a");
}
sleep(5);
if(pthread_cancel(tid_b) != 0)
{
perror("pthread_cancel tid_b");
}
sleep(5);
if(pthread_cancel(tid_c) != 0)
{
perror("pthread_cancel tid_c");
}
sleep(30);
printf("the main close\n");
return 0;
}