《UNIX环境高级编程》笔记--线程的取消选项

来源:互联网 发布:房租占收入比例 知乎 编辑:程序博客网 时间:2024/04/26 18:09

原文地址:点击打开链接

有两个线程并没有包含在pthread_attr_t机构中,他们是可取消状态和可取消类型,这两个属性影响着线程在响应

pthread_cancel函数调用时所呈现的行为。

可取消状态属性可以是PTHREAD_CANCEL_ENABLE和PTHREAD_CANCEL_DISABLE,线程可以通过调用

pthread_setcancelstate修改它的可取消状态。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include<pthread.h>  
  2. int pthread_setcancelstate(int state, int *oldstate);  
  3. //成功则返回0,否则返回错误编号。  
pthread_setcancelstate把当前可取消状态设置为state,把原来的可取消状态存放在oldstate指向的内存单元中,这两

步是原子操作。

pthread_cancel并不等待线程终止,在默认情况下,线程在取消请求发出以后还是继续运行,直到线程到达某个取消点。

取消点是线程检查是否被取消并按照请求进行动作的一个位置。POSIX.1保证在下表中列出的任何函数,取消点都会出现。


下表POSIX.1定义的可选取消点:


线程启动是默认的可取消状态是PTHREAD_CANCEL_ENABLE。当状态设为PTHREAD_CANCEL_DISABLE时,对pthread_cancel的调用并不会杀死

线程,相反,取消请求对这个线程来说处于未决状态。当取消状态再次变成PTHREAD_CANCEL_ENABLE时,线程将在下一个取消点上对所有未决的取消

请求进行处理。

如果应用程序在很长一段时间内都不会调用到上面的函数,那么可以调用pthread_testcancel函数在程序中自己添加取消点。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include<pthread.h>  
  2. void pthread_testcancel(void);  
调用pthread_testcancel时,如果有个取消请求正处于未决状态,而且取消并没有设置为无效,那么线程就会被取消。但是如果

取消被置成无效,pthread_testcancel调用就没有任何效果。


这里所描述的默认取消类型也称为延迟取消,调用pthread_cancel以后,在线程到达取消点之前,并不会出现真正的取消,

可以通过调用pthread_setcanceltype来修改取消类型。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include<pthread.h>  
  2. int pthread_setcanceltype(int type, int *oldtype);  
  3. //成功则返回0,否则返回错误编号。  
type参数可以是PTHERAD_CANCEL_DEFERRED(延迟取消)或PTHREAD_CANCEL_ASYNCHRONOUS(异步取消),

使用异步取消时,线程可以在任何时间取消,而不是非要等到遇到取消点才能被取消。


实践:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include <stdio.h>  
  2. #include <pthread.h>  
  3. #include <string.h>  
  4.   
  5. pthread_t tid1,tid2;  
  6.   
  7. void* func1(void* arg){  
  8.         printf("pause start\n");  
  9.         sleep(10);  
  10.         printf("pause end\n");  
  11.         pthread_exit((void*)0);  
  12. }  
  13.   
  14. void* func2(void* arg){  
  15.         pthread_cancel(tid1);  
  16.         pthread_exit((void*)0);  
  17. }  
  18.   
  19. int main(void){  
  20.         int err;  
  21.         err = pthread_create(&tid1,NULL,func1,NULL);  
  22.         if(err != 0){  
  23.                 printf("pthread_create:%s\n",strerror(err));  
  24.                 return -1;  
  25.         }  
  26.         sleep(2);  
  27.         err = pthread_create(&tid2,NULL,func2,NULL);  
  28.         if(err != 0){  
  29.                 printf("pthread_create:%s\n",strerror(err));  
  30.                 return -1;  
  31.         }  
  32.   
  33.         err = pthread_join(tid1, NULL);  
  34.         if(err != 0){  
  35.                 printf("pthread_join:%s\n",strerror(err));  
  36.                 return -1;  
  37.         }  
  38.         err = pthread_join(tid2, NULL);  
  39.         if(err != 0){  
  40.                 printf("pthread_join:%s\n",strerror(err));  
  41.                 return -1;  
  42.         }  
  43.         return 0;  
  44. }  
运行结果:

yan@yan-vm:~/apue$ ./a.out
pause start
yan@yan-vm:~/apue$

线程能够在运行pause函数时取消。


我们修改下程序,再运行一下:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include <stdio.h>  
  2. #include <pthread.h>  
  3. #include <string.h>  
  4.   
  5. pthread_t tid1,tid2;  
  6.   
  7. void* func1(void* arg){  
  8.         int err;  
  9.         err = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);  
  10.         if(err != 0){  
  11.                 printf("pthread_setcancelstate:%s\n",strerror(err));  
  12.                 pthread_exit((void*)-1);  
  13.         }  
  14.         printf("pause1 start\n");  
  15.         sleep(10);  
  16.         printf("pause1 end\n");  
  17.   
  18.         err = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);  
  19.         if(err != 0){  
  20.                 printf("pthread_setcancelstate:%s\n",strerror(err));  
  21.                 pthread_exit((void*)-1);  
  22.         }  
  23.         printf("pause2 start\n");  
  24.         pthread_testcancel();  
  25.         printf("pause2 end\n");  
  26.         pthread_exit((void*)0);  
  27. }  
  28.   
  29. void* func2(void* arg){  
  30.         pthread_cancel(tid1);  
  31.         pthread_exit((void*)0);  
  32. }  
  33.   
  34. int main(void){  
  35.         int err;  
  36.         err = pthread_create(&tid1,NULL,func1,NULL);  
  37.         if(err != 0){  
  38.                 printf("pthread_create:%s\n",strerror(err));  
  39.                 return -1;  
  40.         }  
  41.         sleep(2);  
  42.         err = pthread_create(&tid2,NULL,func2,NULL);  
  43.         if(err != 0){  
  44.                 printf("pthread_create:%s\n",strerror(err));  
  45.                 return -1;  
  46.         }  
  47.   
  48.         err = pthread_join(tid1, NULL);  
  49.         if(err != 0){  
  50.                 printf("pthread_join:%s\n",strerror(err));  
  51.                 return -1;  
  52.         }  
  53.         err = pthread_join(tid2, NULL);  
  54.         if(err != 0){  
  55.                 printf("pthread_join:%s\n",strerror(err));  
  56.                 return -1;  
  57.         }  
  58.         return 0;  
  59. }  
运行结果:

yan@yan-vm:~/apue$ ./a.out
pause1 start
pause1 end
pause2 start
yan@yan-vm:~/apue$

第一次线程为不可取消状态,sleep函数没有被打断。第二次线程为可取消状态,在执行pthread_testcancel函数时被打断,

线程被取消。

0 0
原创粉丝点击