数据类型:pthread_attr_t
操作API:
// 初始化线程属性 int pthread_attr_init(pthread_attr_t *attr);// 初始化为系统支持的所有属性的默认值 ------------------------------------------------------------------------------------- // 销毁线程属性 int pthread_attr_destroy(pthread_attr_t *attr);// 回收初始化时给此属性分配的资源
1:分离属性
描述:分离线程终止时由系统回收线程资源,而一般线程需要pthread_join(pthread_t)函数来回收资源
// 设置分离线程属性 int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate); detachstate可取两个值: 1:默认是PTHREAD_CREATE_JOINABLE,不特意设置线程属性时默认是它 2:PTHREAD_CREATE_DETACHED(线程分离) ------------------------------------------------------------------------------------- // 获得分离属性 int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate); 例:设置分离属性的线程 int makedetachpthread(void *(*fn)(void *), void *arg) { int err; pthread_t tid; pthread_attr_t attr; err = pthread_attr_init(&attr); if(err != 0){ return err; } err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); if(err == 0) pthread_create(&tid, &attr, fn, arg); pthread_attr_destroy(&attr);// 这里对destroy的返回值没有检查,默认是能够正确回收attr的资源 return err; }
2:堆栈大小及起始地址属性
描述:线程的堆栈是使用的进程的堆栈,进程的堆栈是有限的,所以在某些嵌入式程序中会合理设置线程堆栈大小
// 设置线程堆栈大小 /* 如果堆栈空间不足,pthread_create将返回err=12,在<limits.h>中定义#define ENOMEM 12 // Out of memory 设置的栈区大小不能小于PTHREAD_STACK_MIN */ int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize); // 获得当前线程堆栈大小 int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize); ------------------------------------------------------------------------------------- // 设置线程堆栈大小及自定义堆栈空间 /* 如上所说,进程的堆栈空间是有限的,如果此时堆栈空间已经使用完,而你还想继续创建线程,那么此线程只能放在别处 下面的函数比pthread_attr_setstacksize多了一个stackaddr参数,用于指定放置线程的起始地址(通常是用malloc分配堆 上空间来使用). */ int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, size_t stacksize); // 获取线程堆栈的起始地址和堆栈大小 int pthread_attr_getstack(pthread_attr_t *attr, void **stackaddr, size_t *stacksize);
3:堆栈警戒区属性
描述:警戒区的意义在于,允许线程在超出线程栈后还能操作一段栈空间(会有警告消息发送给它),
// 设置线程栈警戒区 /* 警戒区默认大小是一页字节guardsize设置为0表示不提供警戒区机制,注意的是:当使用pthread_attr_setstack改变了stackaddr参数后,系统默认应用 程序自己管理警戒区,类似将guardsize设置为0. */ int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize); // 获取线程警戒区大小 int pthread_attr_getguardsize(pthread_attr_t *attr, size_t *guardsize);
注:下面的两个线程属性是不包含在pthread_attr_t数据结构中的,分别是取消状态和取消类型。
可知这两个属性是回应pthread_cancel函数的,pthread_cancel函数只是对某个同一线程中的某个线程发出取消请求(好比目标线程调用pthread_exit(PTHREAD_CANCELED)),至于目标线程如何处理这个请求,就是这两个属性来定义的.
1:取消状态属性
// 设置取消状态 int pthread_setcancelstate(int state, int *oldstate) state取值: PTHREAD_CANCEL_ENABLE: 默认值,表示接受其他线程pthread_cancel取消信号 PTHREAD_CANCEL_DISABLE: 阻塞线程pthread_cancel取消信号,当状态改为PTHREAD_CANCEL_ENABLE时再依次处理请求
既然本线程收到了取消的请求,那么我什么时候执行取消动作呢?这就引出了取消点的概念,线程会在取消点处处理取消请求(处理方式就是调用pthread_exit(PTHREAD_CANCELED)),取消点可能会出现在下列函数中:
也可以自己设置取消点的位置:
// 手动设置取消点的位置 void pthread_testcancel(void);
当然,设置取消点要生效还是得取消状态值是:PTHREAD_CANCEL_ENABLE的情况下.
2:取消类型属性
前面所讲,获得取消请求之后线程要到取消点才执行取消动作,这其实是一种取消类型属性,叫做延迟取消(deferred cancel)类型,还有一种叫异步取消类型,这种类型就不需要等到取消点才执行取消动作,线程可以在任意时间取消.
// 设置取消类型 int pthread_setcanceltype(int type, int *oldtype) type取值: PTHREAD_CANCEL_DEFERRED: 默认值,延迟到取消点才执行取消动作 PTHREAD_CANCEL_ASYNCHRONOUS: 随时会执行取消动作