线程控制:线程属性分析(三)

然后再来说说不在Pthread_attr_t结构中的线程属性

线程的可取消状态和可取消类型这两个属性。
这两个属性影响这线程在响应pthread_cancel函数调用时所呈现的行为


可取消状态属性有两种:PTHREAD_CANCEL_ENABLE(线程默认取消状态) 和PTHREAD_CANCEL_DISABLE

int pthread_setcancelstate(int state,int *oldstate);
该函数可以设置线程的取消状态并吧原来的可取消状态存放在oldstate中。
当线程取消状态设置为 PTHREAD_CANCEL_DISABLE时,pthread_cancel的调用不会杀死线程,相反取消请求对这个线程来说
是未决状态,当取消状态再次变为PTHREAD_CANCEL_ENABLE时,线程将在下一个取消点上对所有未决的取消请求进行处理
所谓取消点:就是当线程可以响应pthread_cancel的取消请求时,他不是立刻就结束的而是等到执行到取消点时再结束
比如read,write,open等都是定义的取消点
void pthread_testcancel(void) 该函数可以用来在程序中自己添加取消点。

再来说可取消类型属性。上面说的取消类型可以说都是延迟取消。因为线程在响应Pthread_cancel(取消状态为ENABLE,才能响应)后,并不会
立刻取消,而是要等到执行到一个取消点时才会真正结束
所以取消类型属性也有两种: 延迟取消 PTHREAD_CANCEL_DEFERRED (线程默认取消类型)
异步取消 PTHREAD_CANCEL_ASYNCHRONOUS(线程可在任意时间取消,而不是非要等到取消点)
int pthread_setcanceltype(int type,int *oldtype);
该函数用来设置线程取消类型,并吧原来的取消类型放在oldtype中。


下面给个具体具体的例子

主线程中我们创建一个新线程,然后立刻调用ptrhread_cancel取消该线程,之后睡眠4秒。因为默认是延迟取消,所以新线程不会立刻结束,他执行的第一句是pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL)并且这个函数不是一个取消点;那么现在对于子线程来说 取消状态属性是不响应取消也就是刚刚主线程的取消请求对子子线程来说现在是未决的,(第五行先注释掉,不执行)然后新线程循环输出三次次。我们用了两个输出,一个是pinrtf另一个是write。
write是定义的取消点而printf不是。用来个是用来验证 延迟与异步的区别。当循环到第三次输出的时候。新线程会设置 取消状态为可取消。
那么之前未决的那个取消请求 此时会被应答。然后程序执行到取消点write才结束。也就是前面的那个printf还是会输出但是write就不会输出了

程序如下
   void *th1(void *arg){
           pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
          int i;
          char *str="thread is running\n";
  5 //   pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
           for(i=0;i<10;i++){
                  printf("a\n");
                  write(1,str,strlen(str));
                  sleep(1);
                  if(i==2){
                          pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
                  }
          }
          pthread_exit((void *)0);
  }
  
  int main(void){
          pthread_t tid;
          pthread_create(&tid,NULL,th1,(void *)0);
          pthread_cancel(tid);
          sleep(4);
          void *res;
          pthread_join(tid,&res);
          if(res==PTHREAD_CANCELED){
                  printf("exit code:PTHREAD_CANCELED\n");
          }else{
                  printf("exit code:%d\n",(int)res);
          }
          exit(0);
  
  }
我们来看下输出:
a
thread is running
a
thread is running
a
thread is running
a
exit code:PTHREAD_CANCELED
如我们预想的  输出到第四次后 printf(“a\n”);还是会执行,但是应为write是定义的取消点,在这里线程会结束,所以write就不会输出了

现在我们把第5行的注释去掉,让他可以执行。再来看看输出。执行第八行后 线程的输出被设置为 异步的,也就是可以任意时刻被取消。
当第三次输出后,线程取消状态被设置为可取消后,之前的那个未决的取消请求这个时候会被立刻响应,线程会立刻结束
a
thread is running
a
thread is running
a
thread is running
exit code:0
输出如我们锁预想的。第三次输出完后,线程会立刻结束,所以第四次的printf("a\n");也未执行。
还要注意到一点。设置为异步取消类型后,线程响应取消后的返回值为0.而不在是PTHREAD_CANCELED。即使将上面的程序
中的pthread_exit修改为返回别的值,线程结束也还是返回0.

最后关于线程的并发度属性。有两个接口:


int pthread_getconcurrency(void); //获得当前的并发度
int pthread_setconcurrency(int level); //设定并发度,但这只是对系统的一个提示,系统化并不保证请求一定会被采用

并发度控制着用户级线程可以映射到内核级线程或进程的数目,如果操作系统的实现在内核级的线程和用户级的线程之间保持一一对应的映射,那么改变并发度并不会有什么效果。因为所有的用户级线程都可能被调度到。但是如果操作系统的实现让用户级线程到内核级线程或进程之间的映射关系是多对一的话,那么在给定的时间内增加可运行的用户级线程数,可能会改善性能。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值