我们一般创建线程是这样
pthread_t tid;
pthread_create(&tid, NULL, func, NULL);
第二个参数是线程属性设置,一般设置为了NULL,但是可以通过系统API进一步设置第二个参数,细化创建的线程的属性。
大致步骤为:
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setXXX(&attr, 目标值);
……//创建线程,其他代码
pthread_attr_destroy(&attr);
通过一系列的set函数设置pthread_attr_t类型结构体attr的值。
1.线程分离状态
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int*detachstate);
int pthread_attr_setdetachstate(pthread_attr_t *attr, intdetachstate);
设置线程的分离状态为PTHREAD_CREATE_JOINABLE或PTHREAD_CREATE_DETACHED。
默认是joinable,有一些资源会在线程结束后仍然保持占用状态,直到另外的线程对这个线程使用pthread_join。detached线程不是这样子的,它没有被其他的线程所等待(join),自己运行结束了,线程也就终止了,马上释放系统资源。
若成功返回0,若失败返回-1。
2.线程的调度策略
int pthread_attr_getschedpolicy(const pthread_attr_t *restrict attr,
int *restrict policy);
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
设置调度策略为SCHED_OTHER、SCHED_FIFO、SCHED_RR。默认调度为other。
若成功返回0,若失败返回-1。
3.线程的调度参数
int pthread_attr_getschedparam(const pthread_attr_t *restrict attr,
struct sched_param *restrictparam);
int pthread_attr_setschedparam(pthread_attr_t *restrict attr,
const struct sched_param*restrict param);
结构param的子成员__sched_priority控制一个优先权值,大的优先权值对应高的优先权。
若成功返回0,若失败返回-1。
4.线程的继承调度
int pthread_attr_getinheritsched(constpthread_attr_t *restrict attr,
int*restrict inheritsched);
int pthread_attr_setinheritsched(pthread_attr_t*attr, int inheritsched);
设置线程是否继承父线程的调度,即此线程的调度策略及优先级是继承于父线程,还是通过set设定两个属性。值为:PTHREAD_INHERIT_SCHED,PTHREAD_EXPLICIT_SCHED。
默认是inherit继承父线程的。
若成功返回0,若失败返回-1。
5.线程的竞争范围
int pthread_attr_getscope(const pthread_attr_t *restrict attr,
int *restrict contentionscope);
int pthread_attr_setscope(pthread_attr_t *attr, int contentionscope);
定义创建的线程的竞争范围为PTHREAD_SCOPE_SYSTEM、PTHREAD_SCOPE_PROCESS。
Linux Threads只实现了PTHREAD_SCOPE_SYSTEM,这意味着,它将和机器上运行的所有进程竞争CPU时间。
标准指定的另外一个值,PTHREAD_SCOPE_PROCESS,表示竞争只存在于运行中的进程的线程之间:即,线程的优先级是相对于其它进程中的线程的优先级的,而不必考虑进程的优先级如何。LinuxThread不支持PTHREAD_SCOPE_PROCESS。
若成功返回0,若失败返回-1。
6.线程的栈的地址和大小
(1)
int pthread_attr_getstack(pthread_attr_t *attr,void **stackaddr,size_t*stacksize);
int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr,size_t stacksize);
设置线程栈的起始地址和栈大小。默认起始地址0,大小0x800000(8M,我的机子……)。
PS:使用get时往往显示的是addr = 0,size = 0,这可能是系统的BUG,size应给为8M而不是0。
(2)
上面的2个函数可以细化成4个:
int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr);
int pthread_attr_getstackaddr(pthread_attr_t *attr, void**stackaddr);
int pthread_attr_setstacksize(pthread_attr_t *attr, size_tstacksize);
int pthread_attr_getstacksize(pthread_attr_t *attr, size_t*stacksize);
这里get得到的size为8M,所以pthread_attr_getstack获得的size大小是不能说明栈的大小的。
7.栈溢出保护区大小
intpthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);
intpthread_attr_getguardsize(pthread_attr_t *attr, size_t *guardsize);
设置线程的栈溢出保护区大小,默认4096B,即4K。
8. 设置/获取线程属性对象里CPU 姻亲属性
int pthread_attr_setaffinity_np(pthread_attr_t *attr,size_tcpusetsize,
const cpu_set_t *cpuset);
int pthread_attr_getaffinity_np(pthread_attr_t *attr, size_tcpusetsize,
cpu_set_t *cpuset);
函数把 attr 引用的线程属性对象中的 CPU 姻亲掩码设置为cpuset 指定的值。这个属性决定了使用线程属性对象 attr 创建的线程的 CPU 姻亲掩码。