线程属性
前篇介绍了使用缺省属性创建线程的基本原理。本章论述如何在创建线程时设置
属性。
注– 只有pthreads 使用属性和取消功能。本章中介绍的API 仅适用于POSIX 线程。除此
之外,Solaris 线程和pthreads 的功能大致是相同的。
属性对象
通过设置属性,可以指定一种不同于缺省行为的行为。使用pthread_create(3C)
创建
线程时,或初始化同步变量时,可以指定属性对象。缺省值通常就足够了。
属性对象是不透明的,而且不能通过赋值直接进行修改。系统提供了一组函数,用于
初始化、配置和销毁每种对象类型。
初始化和配置属性后,属性便具有进程范围的作用域。使用属性时最好的方法即是在
程序执行早期一次配置好所有必需的状态规范。然后,根据需要引用相应的属性对
象。
使用属性对象具有两个主要优点。
■ 使用属性对象可增加代码可移植性。
即使支持的属性可能会在实现之间有所变化,但您不需要修改用于创建线程实体的
函数调用。这些函数调用不需要进行修改,因为属性对象是隐藏在接口之后的。
如果目标系统支持的属性在当前系统中不存在,则必须显式提供才能管理新的属
性。管理这些属性是一项非常容易的移植任务,因为只需在明确定义的位置初始化
属性对象一次即可。
■ 应用程序中的状态规范已被简化。
例如,假设进程中可能存在多组线程。每组线程都提供单独的服务。每组线程都有
各自的状态要求。
在应用程序执行初期的某一时间,可以针对每组线程初始化线程属性对象。以后所
有线程的创建都会引用已经为这类线程初始化的属性对象。初始化阶段是简单和局
部的。将来就可以快速且可靠地进行任何修改。
在进程退出时需要注意属性对象。初始化对象时,将为该对象分配内存。必须将此内
存返回给系统。pthreads 标准提供了用于销毁属性对象的函数调用。
初始化属性
请使用pthread_attr_init(3C)
将对象属性初始化为其缺省值。存储空间是在执行期间
由线程系统分配的。
pthread_attr_init
语法
int pthread_attr_init(pthread_attr_t *tattr);
#include <pthread.h>
pthread_attr_t tattr;
int ret;
/* initialize an attribute to the default value */
ret = pthread_attr_init(&tattr);
表1 给出了属性(tattr) 的缺省值。
属性 | 值 | 结果 |
---|---|---|
scope | PTHREAD_SCOPE_PROCESS |
新线程与进程中的其他线程发生竞争。 |
detachstate | PTHREAD_CREATE_JOINABLE |
线程退出后,保留完成状态和线程ID。 |
stackaddr | NULL | 新线程具有系统分配的栈地址。 |
stacksize | 0 | 新线程具有系统定义的栈大小。 |
priority | 0 | 新线程的优先级为0。 |
inheritsched | PTHREAD_EXPLICIT_SCHED |
新线程不继承父线程调度优先级。 |
schedpolicy | SCHED_OTHER |
新线程对同步对象争用使用Solaris 定义的固定优先级。线程将一直运行,直到被抢占或者直到线程阻塞或停止为止。 |
pthread_attr_init
返回值
pthread_attr_init()
成功完成后将返回零。其他任何返回值都表示出现了错误。如果
出现以下情况,该函数将失败并返回对应的值。
ENOMEM
描述: 如果未分配足够的内存来初始化线程属性对象,将返回该值。
销毁属性
请使用pthread_attr_destroy(3C)
删除初始化期间分配的存储空间。属性对象将会无
效。
pthread_attr_destroy
语法
int pthread_attr_destroy(pthread_attr_t *tattr);
#include <pthread.h>
pthread_attr_t tattr;
int ret;
/* destroy an attribute */
ret = pthread_attr_destroy(&tattr);
pthread_attr_destroy
返回值
pthread_attr_destroy()
成功完成后将返回零。其他任何返回值都表示出现了错误。如
果出现以下情况,该函数将失败并返回对应的值。
EINVAL
描述: 指示tattr 的值无效。
设置分离状态
如果创建分离线程(PTHREAD_CREATE_DETACHED
),则该线程一退出,便可重用其线程ID
和其他资源。如果调用线程不准备等待线程退出,请使用pthread_attr_setdetachstate(3C)
。
pthread_attr_setdetachstate(3C)
语法
int pthread_attr_setdetachstate(pthread_attr_t *tattr,int detachstate);
#include <pthread.h>
pthread_attr_t tattr;
int ret;
/* set the thread detach state */
ret = pthread_attr_setdetachstate(&tattr,PTHREAD_CREATE_DETACHED);
如果使用PTHREAD_CREATE_JOINABLE
创建非分离线程,则假设应用程序将等待线程完
成。也就是说,程序将对线程执行pthread_join()
。
无论是创建分离线程还是非分离线程,在所有线程都退出之前,进程不会退出。
注– 如果未执行显式同步来防止新创建的分离线程失败,则在线程创建者从
pthread_create()
返回之前,可以将其线程ID 重新分配给另一个新线程。
非分离线程在终止后,必须要有一个线程用join 来等待它。否则,不会释放该线程的
资源以供新线程使用,而这通常会导致内存泄漏。因此,如果不希望线程被等待,请
将该线程作为分离线程来创建。
示例1创建分离线程
#include <pthread.h>
pthread_attr_t tattr;
pthread_t tid;
void *start_routine;
void arg
int ret;
/* initialized with default attributes */
ret = pthread_attr_init (&tattr);
ret = pthread_attr_setdetachstate (&tattr,PTHREAD_CREATE_DETACHED);
ret = pthread_create (&tid, &tattr, start_routine, arg);
pthread_attr_setdetachstate
返回值
pthread_attr_setdetachstate()
成功完成后将返回零。其他任何返回值都表示出现了
错误。如果出现以下情况,该函数将失败并返回对应的值。
EINVAL
描述: 指示detachstate 或tattr 的值无效。
获取分离状态
请使用pthread_attr_getdetachstate(3C)
检索线程创建状态(可以为分离或连接)。
pthread_attr_getdetachstate
语法
int pthread_attr_getdetachstate(const pthread_attr_t *tattr,
int *detachstate)
#include <pthread.h>
pthread_attr_t tattr;
int detachstate;
int ret;
/* get detachstate of thread */
ret = pthread_attr_