线程终止与线程属性

一.线程终止方式及测试

1.线程终止方法

如果需要只终止某个线程而不终止某个进程,可以有三种方法:

  • 非主线程线程从线程函数中return,此方法对主线程不适用,从main函数return相当于调用exit,会导致整个进程结束;
  • 一个线程可以调用pthread_cancle终止同一进程中的另一个线程。
  • 线程可以调用pthread_exit来终止自己,主控线程如果只想自己的线程终止,可以用pthread_exit来结束主控线程而其他线程和总进程不受影响。

注意:同一个线程间,pthread_cancel向另一个线程发出终止信号,系统并不会马上关闭被取消线程,只有在被取消线程下次调用时,才会真正结束线程。或调用pthread_testcancel,让内核去检测是否需要取消当前线程,pthread_testcancle会产生系统调用,如果需要的停止的话调用完pthread_testcancel就真正的将线程终止了。

2.内核检测终止线程测试

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
void *thread_func(void* arg)
{
  int *p = (int*)arg;
  int i = 0;
  printf("thread PID = %d\n",getpid());
  printf("thread ID = %x.\n",(unsigned int)pthread_self());
  printf("thread *arg = %d.\n",*p);
  while(1)
  {
    i++;
    pthread_testcancel();//转入内核检测,产生系统调用,使得线程可真正地被cancel,其实这里只要可以陷入内核态,就可以真正使得线程被cancel
    // 使用 ps -eLf | grep 进程名 可以查看线程是否真正被终止了,注释掉或不注释掉上一行代码进行正向测试和反向测试
  }
}
int main(void)
{
  pthread_t tid;
  int n = 10;
  pthread_create(&tid,NULL,thread_func,(void*)&n);
  printf("main thread ID = %x.\n",(unsigned int)pthread_self());
  printf("main child thread id= %x.\n",tid);
  printf("main PID= %d.\n",getpid());
  pthread_cancel(tid);
  while(1)
    sleep(1);
  return 0;
}

二.线程属性

1.线程属性的定义

给出抽象定义和在glibc-2.31.tar中的原始定义(glibc-2.31.tar源码包下载路径:http://ftp.gnu.org/pub/gnu/glibc/

抽象定义:
typedef struct
{
    int etachstate;              //线程的分离状态
    int schedpolocy;             //线程调度策略
    struct sched_param schedparam;//线程的调度参数
    int inherited;               //线程的继承性
    int scope;                   //线程的作用域
    size_t gaurdsize;            //线程栈末尾的警戒缓冲区大小
    int stackaddr_set;           //线程的栈设置
    void* stackaddr;             //线程栈位置
    size_t stack_size;           //线程栈大小
} pthread_attr_t;

原始定义(其实和抽象定义没差很多,只是一些数据类型具体了):
给出在glibc-2.31.tar中的定义,定义随着版本的不一样可能会有改变,但最近版本变动应该不是很大:
在pthreadtypes.h中定义:
typedef struct __pthread_attr pthread_attr_t;
struct___pthread_attr.h中定义:
struct __pthread_attr
{
  struct sched_param __schedparam;                   //线程调度策略
  void *__stackaddr;                                 //线程栈位置,线程的栈设置
  size_t __stacksize;                                //线程栈大小            
  size_t __guardsize;                                //线程栈末尾的警戒缓冲区大小
  enum __pthread_detachstate __detachstate;          //线程的分离状态
  enum __pthread_inheritsched __inheritsched;        //线程的继承性
  enum __pthread_contentionscope __contentionscope;  //线程的作用域
  int __schedpolicy;                                 //线程调度策略
};

注意:线程的属性值不能直接设置,需要使用相关函数进行操作,初识化的函数为pthread_attr_init,如果需要对线程属性值进行特殊设置,必须在创建线程函数pthread_create之前用pthread_attr_init对线程属性进行初始化,用过之后需要调用pthread_attr_destroy函数来释放资源。线程属性主要如上显示,默认的属性为非绑定,非分离,缺省M的堆栈(缺省值对于不同平台来说的大小可能是不一样的,可通过unlimt -a查看,显示的stack size的即为堆栈缺省值,比如我的3.10.0-957.el7.x86_64是8M,2.6.32-754.el6.i686 的是10M),与父进程同样级别的优先级。

补充:uname -a查看系统版本。

2.线程属性的初始化

先初始化线程属性,再用pthread_create创建线程:

NAME
       pthread_attr_init, pthread_attr_destroy - initialize and destroy thread attributes object

SYNOPSIS
       #include <pthread.h>
       int pthread_attr_init(pthread_attr_t *attr);//初始化线程属性
       int pthread_attr_destroy(pthread_attr_t *attr);//销毁线程属性所占用的资源
       Compile and link with -pthread.
DESCRIPTION
       The  pthread_attr_init()  function  initializes  the thread attributes object pointed to by attr with default attribute values.  After this call, individual attributes of the object can be set using various related functions (listed under SEE ALSO), and then the object can be used in one or more pthread_create(3) calls that create threads.
       Calling pthread_attr_init() on a thread attributes object that has already been initialized results in undefined behavior.
       When a thread attributes object is no longer required, it should be destroyed using the pthread_attr_destroy() function.  Destroying a thread attributes object has no effect on  threads  that  were  created using that object.
       Once a thread attributes object has been destroyed, it can be reinitialized using pthread_attr_init().  Any other use of a destroyed thread attributes object has undefined results.
RETURN VALUE
       On success, these functions return 0; on error, they return a non-zero error number.
ERRORS
       POSIX.1-2001 documents an ENOMEM error for pthread_attr_init(); on Linux these functions always succeed (but portable and future-proof applications should nevertheless handle a possible error return).

3.线程的分离状态(detached status)

线程的分离状态决定了一个线程以什么样的方式结束自己的一生。

  1. 非分离状态:线程的默认属性是非分离状态,这种情况下,原有的线程等待创建的线程结束。只有当pthread_join()函数返回超时是,创建的线程才算终止,才能释放自己占用的系统资源。
  2. 分离状态:分离状态没有被其他的线程所等待,自己运行结束了,线程也就终止了,马上释放系统资源,应该根据自己的需要,选择适当的分离状态。

 分离状态函数:

头文件及函数原型: 
  #include <pthread.h>
    //设置线程的分离状态:分离或者不分离
    int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
    //获取线程的分离状态:分离或者不分离
    int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate);
    
参数解释:
   pthread_attr_t *attr 已被初始化的线程属性
   int *detachstate     分离属性,可选择PTHREAD_CREATE_DETACHED(分离的)和PTHREAD_CREATE_JOINABLE(非分离的)
   默认是非分离的。

返回值:
       On success, these functions return 0; on error, they return a non-zero error number.
ERRORS:
       pthread_attr_setdetachstate(3) can fail with the following error:
       EINVAL An invalid value was specified in detachstate.


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值