一、线程取消
将正在运行的线程取消执行,一个线程可以取消另一个线程,线程也可以自己取消自己。当线程被取消之后,会调用清理函数 。
二、取消函数
int pthread_cancel(pthread_t tid)
取消tid指定的线程,成功返回0。但是取消只是发送一个请求,并不意味着等待线程终止,而且发送成功也不意味着tid一定会终止。
三、取消状态
1、概念
取消状态,就是线程对取消信号的处理方式,忽略或者响应。线程创建时默认响应取消信号。
2、函数
int pthread_setcancelstate(int state, int *oldstate)
设置本线程对Cancel信号的反应,state有两种值:PTHREAD_CANCEL_ENABLE(缺省)和PTHREAD_CANCEL_DISABLE,分别表示收到信号后设为CANCLED状态和忽略CANCEL信号继续运行;old_state如果不为NULL则存入原来的Cancel状态以便恢复。
四、取消类型
1、概念
取消类型,是线程对取消信号的响应方式,立即取消或者延时取消。线程创建时默认延时取消。
2、函数
int pthread_setcanceltype(int type, int *oldtype)
设置本线程取消动作的执行时机,type由两种取值:PTHREAD_CANCEL_DEFFERED和PTHREAD_CANCEL_ASYCHRONOUS,仅当Cancel状态为Enable时有效,分别表示收到信号后继续运行至下一个取消点再退出和立即执行取消动作(退出);oldtype如果不为NULL则存入运来的取消动作类型值。
五、取消点
取消一个线程,它通常需要被取消线程的配合。线程在很多时候会查看自己是否有取消请求。如果有就主动退出, 这些查看是否有取消的地方称为取消点很多地方都是包含取消点,包括:pthread_join()、 pthread_testcancel()、pthread_cond_wait()、 pthread_cond_timedwait()、sem_wait()、sigwait()、write、read
,大多数会阻塞的系统调用。你可以通过man pthreads来查看当前系统中那些操作是取消点 。
六、实例
1、程序框架
2、源代码
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <iostream>
#include "include/pthread.h"
#ifndef _WIN64
#pragma comment(lib,".\\lib32\\pthreadVC2.lib")
#else
#pragma comment(lib,".\\lib64\\pthreadVC2.lib")
#endif
/*
*int pthread_cancle(pthread_t tid)
* 取消tid指定的线程,成功返回0。但是取消只是发送一个请求,
* 并不意味着等待线程终止,而且发送成功也不意味着tid一定会终止
*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_ASYNCHRONOUS,仅当Cancel状态为Enable时有效,分别表示收到信号
* 后继续运行至下一个取消点再退出和立即执行取消动作(退出);oldtype如果不为NULL
* 则存入运来的取消动作类型值。
*/
void* thread_fun(void* arg) {
int stateval;
int typeval;
stateval = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
if (stateval != 0)
{
printf("set cancel state failed\n");
}
printf("Im new thread\n");
Sleep(4);
printf("about to cancel \n");
stateval = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
if (stateval != 0)
{
printf("set cancel state failed\n");
}
//立即执行取消动作(退出),不打印下面的两句话
typeval = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
if (typeval != 0)
{
printf("set cancel type failed\n");
}
printf("first cancel point\n");
printf("second cancel point\n");
return (void *)0;
}
int main()
{
pthread_t tid;
int err, cval, jval;
void* rval;
err = pthread_create(&tid,NULL,thread_fun,NULL);
if (err!=0)
{
printf("creat new thread failed\n");
return 0;
}
Sleep(2);
cval = pthread_cancel(tid);
if (cval!=0)
{
printf("cancel thread failed \n");
}
jval = pthread_join(tid, &rval);
printf("new thread exit code is %d\n",(int*)rval);
return 0;
}
3、练习:证明线程可以自己取消自己
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <iostream>
#include "include/pthread.h"
#ifndef _WIN64
#pragma comment(lib,".\\lib32\\pthreadVC2.lib")
#else
#pragma comment(lib,".\\lib64\\pthreadVC2.lib")
#endif
/*
*DESCRIPTION: 一个新线程自己可以取消自己
* int pthread_cancel(pthread_t tid)
* 取消tid指定的线程,成功返回0。但是取消只是发送一个请求,并不意味着等待线程终止,
而且发送成功也不意味着tid一定会终止
* int pthread_setcancelstate(int state, int *oldstate)
* 设置本线程对Cancel信号的反应,state有两种值:PTHREAD_CANCEL_ENABLE(缺省)
和PTHREAD_CANCEL_DISABLE,
* int pthread_setcanceltype(int type, int *oldtype)
* 设置本线程取消动作的执行时机,type由两种取值:PTHREAD_CANCEL_DEFFERED和
PTHREAD_CANCEL_ASYCHRONOUS,仅当Cancel状态为Enable时有效,分别表示收到
* 信号后继续运行至下一个取消点再退出和立即执行取消动作(退出);oldtype如果不
为NULL则存入运来的取消动作类型值。
*/
int err;
pthread_t tid;
void* thread_fun(void* arg) {
printf("I'm new thread\n");
printf("I'm about to cancel myself\n");
//设置为延时取消
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
//设置取消状态可以取消
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
//取消自己
err = pthread_cancel(pthread_self());
if (err == 0)
{
printf("cancel myself success\n");
}
else
{
printf("cancel myself failed\n");
}
pthread_exit((void *)0);
return (void*)0;
}
int main()
{
//创造新线程
err = pthread_create(&tid,NULL,thread_fun,NULL);
if (err != 0)
{
printf("create new thread1 failed\n");
return 0;
}
err = pthread_join(tid, NULL);
if (err != 0)
{
printf("main thread join new thread failed\n");
}
else
{
printf("main thread join new thread success\n");
}
return 0;
}