线程的取消学习笔记
目录
取消线程-pthread_cancel:
线程清理:
取消线程-pthread_cancel:
int pthread_cancel(pthread_t thread);//杀死一个线程
示例代码:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>void *func(void *arg)
{printf("This is child thread\n");while (1){sleep(5); //取消点}pthread_exit("thread return");
}
int main()
{void *retv;pthread_t tid;int i; pthread_create(&tid,NULL,func,NULL);sleep(5);pthread_cancel(tid);pthread_join(tid,&retv);printf("thread ret=%s\n",(char *)retv);while (1){sleep(1);}
}
线程取消,必须要设置取消点,如果没有则手动设置。不是说取消就取消,线程的取消点主要是阻塞的系统调用。
运行结果:

出现段错误的问题:
出错原因,retv接收不到字符串,所以不能打印。将printf那一行注释掉就可以。
手动设置取消点代码示例如下:
void *func(void *arg)
{printf("This is child thread\n");while (1){//sleep(5);pthread_testcancel();}pthread_exit("thread return");
}
设置取消使能或禁止
int pthread_setcancelstate(int state, int *oldstate);
示例代码:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>void *func(void *arg)
{printf("This is child thread\n");pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);//前5秒不能取消//while (1){sleep(5);pthread_testcancel();}pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);//后5秒可以取消while (1){sleep(1);}pthread_exit("thread return");
}
int main()
{void *retv;pthread_t tid;int i; pthread_create(&tid,NULL,func,NULL);sleep(5);//不能呢个没有sleep,因为可能线程还没禁止取消就已经取消了pthread_cancel(tid);pthread_join(tid,&retv);//printf("thread ret=%s\n",(char *)retv);while (1){sleep(1);}
}
设置取消类型
int pthread_setcanceltype(int type,int *oldtype);
PTHREAD_CANCEL_DEFERRED //等到取消点才取消(默认是这个)
PTHREAD_CANCEL_ASYNCHRONOUS //目标线程会立即取消
线程清理:
必要性: 当线程非正常终止,需要清理一些资源
void pthread_cleanup_push(void (*routine)(void *),void *arg)
void pthread_cleanup_pop(int execute)
routine函数被执行的条件:
- 被pthread_cancel取消掉
- 执行pthread_exit
- 非0参数执行pthread_cleanup_pop()
示例代码:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>void cleanup1(void *arg)
{printf("cleanup1, arg=%s\n",(char *)arg);
}
void cleanup2(void *arg)
{printf("cleanup2, arg=%s\n",(char *)arg);
}
void *func(void *arg)
{printf("This is child thread\n");pthread_cleanup_push(cleanup1, "abcd");pthread_cleanup_push(cleanup2, "efgh");//while (1){sleep(1);}// pthread_exit("thread return");// pthread_cleanup_pop(0);//必须和前面成对出现// pthread_cleanup_pop(0);//等效于这种写法pthread_cleanup_pop(1);//必须和前面成对出现pthread_cleanup_pop(1);pthread_exit("thread return");
}
int main()
{ void *retv;pthread_t tid;int i; pthread_create(&tid,NULL,func,NULL);sleep(1);//不能呢个没有sleep,因为可能线程还没禁止取消就已经取消了pthread_cancel(tid);pthread_join(tid,&retv);printf("thread return = %s\n",(char *)retv);while(1){sleep(1);}
}
运行结果:

注意:
- 必须成对使用,即时pthread_cleanup_pop不会被执行到也必须写上,否则编译错误。
- pthread_cleanup_pop()被执行且参数为0,pthread_cleanup_push回调函数routine不会被执行。
- pthread_cleanup_push和pthread_cleanup_pop可以写多对,routine执行顺序正好相反
- 线程内return可以结束线程,也可以给pthread_join返回值,但不能触发pthread_cleanup_push里面的回调函数,所以我们结束线程尽量使用pthread_exit退出线程。