Linux下多线程编程之——线程取消
线程除了运行完毕后正常退出外,还可以被撤销,使得线程中途退出并释放资源
一、线程取消函数pthread_cancel():
1、输入参数:线程名称,函数向指定的线程发送终止信号
2、返回参数:发送成功 0, 否则为非 0
3、附加应用:pthread_join(),发送成功也无法保证线程就会终止,因此,调用pthread_cancel()函数后,常常继续调用pthread_join(),等待指定线程退出后,再次继续执行
二、设置线程对cancel的反应函数pthread_setcancelstate():
1、第一个参数:常量PTHREAD_CANCEL_ENABLE、设置线程可以cancel,常量PTHREAD_CANCEL_DISABLE、说明线程不可以cancel
2、第二个参数:老的状态,当不为NULL时保存cancel状态,为线程恢复做好准备
三、设置线程取消时机的函数pthread_setcanceltype():
1、第一个参数:常量PTHREAD_CANCEL_DEFERRED、设置线程运行至下一个取消点退出,常量PTHREAD_CANCEL_ASYNCHRONOUS、说明线程立即退出
2、第二个参数:老的状态,当不为NULL时保存原来的动作类型,为线程恢复做好准备
3、pthread_testcancel()函数检查本线程是否处于cancel状态
四、代码test7_4.c
1 //This is c program code! 2 /* *=+=+=+=+* *** *=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= 3 * 文档信息: *** :~/test7_4.c 4 * 版权声明: *** :(魎魍魅魑)MIT 5 * 联络信箱: *** :guochaoxxl@163.com 6 * 创建时间: *** :2020年11月17日的下午07:25 7 * 文档用途: *** :数据结构与算法分析-c语言描述 8 * 作者信息: *** :guochaoxxl(http://cnblogs.com/guochaoxxl) 9 * 修订时间: *** :2020年第46周 11月17日 星期二 下午07:25 (第322天) 10 * 文件描述: *** :自行添加 11 * *+=+=+=+=* *** *+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+*/ 12 #include <stdio.h> 13 #include <pthread.h> 14 15 #define MAXTHREADS 3 16 17 void *myComprint(void *iData){ 18 int oldState; 19 int oldType; 20 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldState); 21 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldType); 22 int *data = (int *)(iData); 23 for(int i = 0; i < *data; i++){ 24 if((i % 250) == 0){ 25 printf("%d print: %d\n", *data, i); 26 pthread_testcancel(); 27 } 28 } 29 } 30 31 void *myComadd(void *iData){ 32 int oldState; 33 int oldType; 34 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldState); 35 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldType); 36 int sum = 0; 37 int *data = (int *)(iData); 38 for(int i = 1; i < *data; i++){ 39 sum += i; 40 printf("%d add %d\n", i, sum); 41 } 42 } 43 44 void *myCommul(void *iData){ 45 int oldState; 46 //int oldType; 47 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState); 48 int sum = 1; 49 int *data = (int *)(iData); 50 for(int i = 1; i <= *data; i++){ 51 sum *= i; 52 printf("%d mul %d\n", i, sum); 53 } 54 } 55 56 int main(int argc, char **argv) 57 { 58 pthread_t threads[MAXTHREADS]; 59 void *status; 60 int n1 = 25; 61 int n2 = 10000; 62 63 pthread_create(&(threads[0]), NULL, myComprint, &n2); 64 pthread_create(&(threads[1]), NULL, myComadd, &n1); 65 pthread_create(&(threads[2]), NULL, myCommul, &n1); 66 67 for(int i = 0; i <MAXTHREADS; i++){ 68 pthread_cancel(threads[i]); 69 } 70 for(int i = 0; i < MAXTHREADS; i++){ 71 pthread_join(threads[i], &status); 72 if(status == PTHREAD_CANCELED){ 73 printf("thread %d 已经取消!\n", i); 74 }else{ 75 printf("thread %d 不能被取消!\n", i); 76 } 77 } 78 79 return 0; 80 }
五、线程清理
1、线程退出是有时需要清理所占资源,线程清理函数pthread_cleanup_push和pthread_cleanup_pop可以自动释放线程资源
2、清理函数的执行时机:调用pthread_exit时;响应取消线程请求时;以非0参数调用pthread_cleanup_pop时
代码test7_5.c
1 //This is c program code! 2 /* *=+=+=+=+* *** *=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= 3 * 文档信息: *** :~/test7_5.c 4 * 版权声明: *** :(魎魍魅魑)MIT 5 * 联络信箱: *** :guochaoxxl@163.com 6 * 创建时间: *** :2020年11月17日的下午08:02 7 * 文档用途: *** :数据结构与算法分析-c语言描述 8 * 作者信息: *** :guochaoxxl(http://cnblogs.com/guochaoxxl) 9 * 修订时间: *** :2020年第46周 11月17日 星期二 下午08:02 (第322天) 10 * 文件描述: *** :自行添加 11 * *+=+=+=+=* *** *+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+*/ 12 #include <stdio.h> 13 #include <pthread.h> 14 15 #define MAXTHREADS 3 16 17 void *myClear(void *iData){ 18 printf("clear: %c\n", *((char *)iData)); 19 } 20 21 void *myComprint(void *iData){ 22 int oldState; 23 int oldType; 24 25 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldState); 26 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldType); 27 int *data = (int *)(iData); 28 pthread_cleanup_push(myClear, "0"); 29 for(int i = 1; i < *data; i++){ 30 if((i % 250) == 0){ 31 printf("%d printf: %d\n", *data, i); 32 pthread_testcancel(); 33 } 34 } 35 pthread_cleanup_pop(1); 36 } 37 38 void *myComadd(void *iData){ 39 int oldState; 40 int oldType; 41 42 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldState); 43 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldType); 44 45 int sum = 0; 46 int *data = (int *)(iData); 47 48 for(int i = 0; i <= *data; i++){ 49 sum += i; 50 printf("%d add %d\n", i, sum); 51 } 52 } 53 54 void *myCommul(void *iData){ 55 int oldState; 56 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState); 57 int sum = 1; 58 int *data = (int *)(iData); 59 60 for(int i = 1; i <= *data; i++){ 61 sum *= i; 62 printf("%d mul %d\n", i, sum); 63 } 64 } 65 66 int main(int argc, char **argv) 67 { 68 pthread_t threads[MAXTHREADS]; 69 void *status; 70 int n1 = 25; 71 int n2 = 10000; 72 73 pthread_create(&(threads[0]), NULL, myComprint, &n2); 74 pthread_create(&(threads[1]), NULL, myComadd, &n1); 75 pthread_create(&(threads[2]), NULL, myCommul, &n2); 76 77 for(int i = 0; i < MAXTHREADS; i++){ 78 pthread_cancel(threads[i]); 79 } 80 for(int i = 0; i < MAXTHREADS; i++){ 81 pthread_join(threads[i], &status); 82 if(status == PTHREAD_CANCELED){ 83 printf("thread %d 已经取消!\n", i); 84 }else{ 85 printf("thread %d 不能被取消!\n", i); 86 } 87 } 88 89 return 0; 90 }