线程属性
POSIX将栈的大小和调度策略这样的特征封装到一个pthread_attr_t类型的对象中去,用面向对象的方式表示和设置特征。属性对象只在线程创建的时候会对线程产生影响。编写程序时可以先创建一个属性对象,然后再将栈的大小和调度策略这样的特征与属性对象关联起来,之后就可以通过向pthread_create传递相同的线程属性对象来创建多个具有相同特征的线程。通过将各种特征组合到单个对象中区,POSIX避免了用大量参数来调用pthread_create的情况。
下表显示的是线程属性的可设置特征及其相关函数。
特征 | 函数 |
属性对象 | pthread_attr_destory pthread_attr_init |
状态 | pthread_attr_getdetachstate pthread_attr_setdetachstate |
栈 | pthread_attr_getguardsize pthread_attr_setguardsize pthread_attr_getstack pthread_attr_setstack |
调度 | pthread_attr_getinheritsched pthread_attr_setinheritsched pthread_attr_getschedparam pthread_attr_setschedparam pthread_attr_getschedpolicy pthread_attr_setschedpolicy pthread_attr_getscope pthread_attr_setscope |
更多的参考POSIX多线程相关资料...
线程状态
线程状态的可能取值为PTHREAD_CREATE_JOINABLE和PTHREAD_CREATE_DETACHED。
pthread_attr_getdetachstate()用来查看一个属性对象中的线程状态,而pthread_attr_setdetachstate()用来设置一个属性对象中的线程状态。这两个函数的形式为:
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);
int pthread_attr_setdetachstate(const pthread_attr_t *attr, int detachstate);
如前面所述,可以通过调用pthread_detach()函数来分离一个线程,现在也可以通过先设置属性对象的线程状态为PTHREAD_CREATE_DETACHED,并在创建线程时传递这个属性对象,使线程处于分离状态。被分离的线程时不能用pthread_join来等待的。默认情况下,线程时可接合的(PTHREAD_CREATE_JOINABLE)。
下面来做个试验,让子线程处于PTHREAD_CREATE_DETACHED状态,然后看在父线程中调用pthread_join()如何。
先来看创建子线程的默认状态吧!即让子线程把自己的状态给打印出来:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *sayhello(void *args)
{
int i, state;
pthread_attr_t attr;
pthread_attr_init(&attr);
i = pthread_attr_getdetachstate(&attr, &state);
if (state == PTHREAD_CREATE_JOINABLE) {
printf("the state is joinable\nthe value is : %d\n", state);
} else if (state == PTHREAD_CREATE_DETACHED) {
printf("the state is detached\n the value is : %d\n", state);
}
printf("hello, world! I'm son\n");
}
int main(void)
{
int error;
pthread_t son;
error = pthread_create(&son, NULL, sayhello, NULL);
printf("hello, world! I'm father\n");
sleep(1);
return 0;
}
编译执行打印结果如下:
root@book-desktop:/opt/pc_test/multithreading/4# ./main
hello, world! I'm father
the state is joinable
the value is : 0
hello, world! I'm son
继续:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
void *sayhello(void *args)
{
sleep(1);
printf("hello, world! I'm son\n");
}
int main(void)
{
int error;
pthread_t son;
pthread_attr_t attr;
pthread_attr_init(&attr);// 这一步很关键哦!
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
error = pthread_create(&son, &attr, sayhello, NULL);
printf("hello, world! I'm father\n");
//error = pthread_join(son, NULL);
if (pthread_join(son, NULL) == EINVAL) {
printf("the son is not joinable\n");
}
//pthread_cancel(son);
//pthread_exit(NULL);
//sleep(1);
return 0;
}
编译执行:
root@book-desktop:/opt/pc_test/multithreading/4# ./main
hello, world! I'm father
the son is not joinable
到了这里,父线程与子线程的等待关系已经弄得很清楚了,相关手段包括:
1.pthread_join()
2.pthread_exit()
3.pthread_cancel()
4.pthread_detach()以及如下这般:
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
error = pthread_create(&son, &attr, sayhello, NULL);
...