一、线程的属性
线程具有属性,用pthread_attr_t表示,在对该结构进行处理之前必须进行初始化,在使用后需要对其去除初始化。
我们用pthread_attr_init函数对其初始化,用pthread_attr_destroy对其去除初始化。
a、初始化一个线程对象的属性
int pthread_attr_init(pthread_attr_t *attr);
返回值:若是成功返回0,否则返回错误的编号
形 参:
attr 指向一个线程属性的指针
说 明:Posix线程中的线程属性pthread_attr_t主要包括scope属性、detach属性、堆栈地址、堆栈大小、优先级。
pthread_attr_init实现时为属性对象分配了动态内存空间。
头文件:#include <pthread.h>
b、销毁一个线程属性对象
int pthread_attr_destroy(pthread_attr_t *attr);
返回值:若是成功返回0,否则返回错误的编号
形 参:
attr 指向一个线程属性的指针
说 明:经pthread_attr_destroy去除初始化之后的pthread_attr_t结构被pthread_create函数调用,将会导致其返回错误。
头文件:#include <pthread.h>
调用pthread_attr_init之后,pthread_t结构所包含的内容就是操作系统实现支持的线程所有属性的默认值。
如果要去除对pthread_attr_t结构的初始化,可以调用pthread_attr_destroy函数。如果pthread_attr_init实现时为属性对象分配了动态内存空间,pthread_attr_destroy还会用无效的值初始化属性对象,因此如果经pthread_attr_destroy去除初始化之后的pthread_attr_t结构被pthread_create函数调用,将会导致其返回错误。
线程属性的结构体如下:
typedef struct
{
int detachstate; //线程的分离状态
int schedpolicy; //线程调度策略
struct sched_param schedparam; //线程的调度参数
int inheritsched; //线程的继承性
int scope; //线程的作用域
size_t guardsize; //线程栈末尾的警戒缓冲区大小
int stackaddr_set; //线程的栈设置
void * stackaddr; //线程栈的位置
size_t stacksize; //线程栈的大小
} pthread_attr_t;
二、线程的分离状态
线程的分离状态决定一个线程以什么样的方式来终止自己。
在默认情况下线程创建是非分离状态的,这种情况下,原有的线程等待创建的线程结束。只有当pthread_join()函数返回时,创建的线程才算终止,才能释放自己占用的系统资源。
而分离线程不是这样子的,它没有被其他的线程所等待,自己运行结束了,线程也就终止了,马上释放系统资源。程序员应该根据自己的需要,选择适当的分离状态。所以如果我们在创建线程时就知道不需要了解线程的终止状态,则可以pthread_attr_t结构中的detachstate线程属性,让线程以分离状态启动。
a、获取线程分离状态属性
int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate);
返回值:若是成功返回0,否则返回错误的编号
形 参:
attr 指向一个线程属性的指针
detachstate 保存返回的分离状态属性
说 明:获取线程分离状态属性
头文件:#include <pthread.h>
b、修改线程分离状态属性
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
返回值:若是成功返回0,否则返回错误的编号
形 参:
attr 指向一个线程属性的指针
detachstat 有两个取值
PTHREAD_CREATE_DETACHED(分离)
PTHREAD_CREATE_JOINABLE(非分离)
说 明:Posix线程中的线程属性pthread_attr_t主要包括scope属性、detach属性、堆栈地址、堆栈大小、优先级。
头文件:#include <pthread.h>
可以使用pthread_attr_setdetachstate函数把线程属性detachstate设置为下面的两个合法值之一:
设置为PTHREAD_CREATE_DETACHED,以分离状态启动线程;
或者设置为PTHREAD_CREATE_JOINABLE,正常启动线程。可以使用pthread_attr_getdetachstate函数获取当前的datachstate线程属性。
三、线程属性的例程
本例程一个线程设置默认的非分离的属性,一个设置分离属性。设置线程属性后,再调用pthread_join()函数,确认非分离属性的线程在结束后调用pthread_join()函数才能释放资源,分离属性的线程结束后自动释放资源。
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
/*输出状态的属性*/
void out_state(pthread_attr_t* attr)
{
int state;
if(pthread_attr_getdetachstate(attr,&state)!=0)
{
perror("get detach state error!\r\n");
}
else
{
if(state==PTHREAD_CREATE_JOINABLE)
{
printf("joinable state!\r\n");
}
else
if(state==PTHREAD_CREATE_DETACHED)
{
printf("detach state!\r\n");
}
else
{
printf("error state!\r\n");
}
}
}
/*线程功能函数*/
void *thread_fn(void *arg)
{
int i,sum;
for(i=0;i<100;i++)
{
sum+=i;
}
return (void*)sum;
}
int main()
{
int err;
int result;
/*创建两个线程,一个默认线程与一个分离线程*/
pthread_t th_fn,detach_fn;
/*定义线程属性*/
pthread_attr_t attr;
/*初始化线程的属性*/
pthread_attr_init(&attr);
/*输出线程属性*/
out_state(&attr);
/*以默认属性创建线程,默认创建的线程是非分离的,线程结束后不释放资源*/
if((err=pthread_create(&th_fn,&attr,thread_fn,(void*)0))!=0)
{
perror("th_fn tread create fail!\r\n");
}
if(err=pthread_join(th_fn,(void*)&result)!=0)
{
perror("pthread_join error!\r\n");
}
else
{
printf("Thread return is %d\r\n",(int)result);
}
printf("-------------------------------------------------\n");
/*以分离属性创建线程,线程结束后自动释放资源*/
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
out_state(&attr);
if((err=pthread_create(&detach_fn,&attr,thread_fn,(void*)0))!=0)
{
perror("detach_fn tread create fail!\r\n");
}
if(err=pthread_join(detach_fn,(void*)&result)!=0)
{
// perror("pthread_join error!\r\n");
fprintf(stderr,"%s\n",strerror(err));
}
else
{
printf("detach return is %d\r\n",(int)result);
}
/*销毁线程属性*/
pthread_attr_destroy(&attr);
printf("0x%lx finished\r\n",pthread_self());
sleep(1);
return 0;
}
输出的结果:可看到分离属性的线程,pthread_join()之后会出现出错,且operation not permitted。