线程属性
默认属性可以解决大多数情况,但是如果对性能有更高的要求,就可以通过修改线程属性,降低线程栈的大小,来减少内存的使用。
设置线程属性的结构体:
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;
主要结构体成员:
1.线程分离状态 detachstate
2.线程栈大小(默认平均分配) stacksize
3.线程栈警备缓冲区大小(位于栈末尾) guardsize
属性值不能直接设置,需要用相应的函数操作。
相关函数
线程属性初始化:
函数原型:int pthread_attr_init(pthread_attr_t *attr)
返回值:成功返回0,失败返回错误号
参数:attr:设置属性的结构体
注意:需要先初始化属性,然后设置相关属性,再创建线程。
销毁线程属性:
函数原型:int pthread_attr_destroy(pthread_attr_t *attr)
返回值:成功返回0,失败返回错误号
参数:要销毁的线程属性
获取线程分离状态:
函数原型:int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate)
返回值:成功返回0,失败返回错误码
参数:attr:设置属性的结构体;detachstate:传入参数,获取状态,PTHREAD_CREATE_DETACHED(分离态)PTHREAD_CREATE_JOINABLE(非分离态)。
设置线程分离状态:
函数原型:int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
返回值:成功返回0.失败返回错误码
参数:attr:设置属性的结构体;detachstate:传出参数,设置状态,PTHREAD_CREATE_DETACHED(分离态)PTHREAD_CREATE_JOINABLE(非分离态)。
获取线程的栈大小:
函数原型:int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize);
返回值:成功返回0,失败返回错误码
参数:attr:设置属性的结构体;stacksize:默认的栈的大小
设置线程的栈大小:
函数原型:int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
返回值:成功返回0,失败返回错误码
参数:attr:设置属性的结构体;stacksize:传入参数,将设置的栈的大小
获取线程的栈的首地址和大小:
函数原型:int pthread_attr_getstack(pthread_attr_t *attr, void **stackaddr, size_t *stacksize);
返回值:成功返回0,失败返回错误码
参数:attr:设置属性的结构体;stackaddr:传出参数,栈的首地址;stacksize:传出参数,栈的大小
设置线程的栈的首地址和大小:
函数原型:int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, size_t stacksize);
返回值:成功返回0,失败返回错误码
参数:attr:设置属性的结构体;stackaddr:传入参数,新的栈的首地址;stacksize:传入参数,设置的栈的大小
当剩下的栈空间不够的时候,我们可以通过malloc函数或者mmap分配的空间作为新的栈的空间。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#define SIZE 0x100000
void *th_fun(void *arg)
{
while (1)
sleep(1);
}
int main(void)
{
pthread_t tid;
int err, detachstate, i = 1;
pthread_attr_t attr;
size_t stacksize;
void *stackaddr;
pthread_attr_init(&attr); //初始化线程属性
pthread_attr_getstack(&attr, &stackaddr, &stacksize); //获取栈的信息
pthread_attr_getdetachstate(&attr, &detachstate); //获取分离态信息
if (detachstate == PTHREAD_CREATE_DETACHED) //如果是分离态
printf("thread detached\n");
else if (detachstate == PTHREAD_CREATE_JOINABLE) //如果不是分离态
printf("thread join\n");
else
printf("thread unknown\n");
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); //将线程设置为分离态
while (1) {
stackaddr = malloc(SIZE); //申请内存
if (stackaddr == NULL) {
perror("malloc");
exit(1);
}
stacksize = SIZE;
pthread_attr_setstack(&attr, stackaddr, stacksize); //设置栈大小
err = pthread_create(&tid, &attr, th_fun, NULL);
if (err != 0) {
printf("%s\n", strerror(err));
exit(1);
}
printf("%d\n", i++);
}
pthread_attr_destroy(&attr);
return 0;
}
线程使用注意事项:
1.malloc和mmap申请的内存可以被其它线程释放(因为堆空间共享)
2.避免有僵尸线程,浪费资源
3.如果在多线程中调用fork并且不马上exec,那除了调用fork的线程存在,其它的线程全部都会pthread_exit。
同步属性
互斥量属性
互斥量属性结构体(pthread_mutexattr_t
)
互斥量有3个属性:
- 进程共享属性(pshared)
- 健壮属性(robust)
- 类型属性(type)
**互斥量属性的创建、销毁
**进程共享属性(pshared)
进程共享属性是指:允许相互独立的多个进程把同一个内存数据块映射到它们各自独立的地址空间中。就像多个线程访问共享数据一样,多个线程访问共享数据也需要同步(互斥)
线程只能访问该进程下的地址空间,可以通过设置进程共享属性使得线程可以访问其他进程的地址空间。
pthread_mutexattr_setpshared:修改进程共享属性
pthread_mutexattr_getpshared:得到进程共享属性
#include <pthread.h>
int pthread_barrierattr_setpshared(pthread_mutexattr_t* attr, int pshared);
int pthread_barrierattr_getpshared(const pthread_mutexattr_t* restrict attr, int* restrict pshared);
//返回值:成功返回0; 失败返回错误编码
**类型属性(type)
*
* 函数功能:获取或修改类型属性;
* 返回值:若成功则返回0,否则返回错误编码;
* 函数原型:
*/
int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type);//获取互斥量的类型属性
int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type);//修改互斥量的类型属性
读写锁属性
读写锁属性结构体(pthread_rwlockattr_t
)
** 读写锁属性结构体的初始化
#include <pthread.h>
int pthread_rwlockattr_init(pthread_rwlockattr_t* attr);
int pthread_rwlockattr_destroy(pthread_rwlockattr_t* attr);
//返回值:成功返回0;失败返回错误编码
** 读写锁进程共享属性的设置与获取(pshared) 唯一
#include <pthread.h>
int pthread_rwlockattr_setshared(pthread_rwlockattr_t* attr,int pshared);
int pthread_rwlockattr_getshared(const pthread_rwlockattr_t* restrict attr,int* restrict pshared);
//返回值:成功返回0;失败返回错误编码
条件变量属性
条件变量属性结构体(pthread_condattr_t
)
** 条件变量属性结构体的初始化
#include <pthread.h>
int pthread_condattr_init(pthread_condattr_t* attr);
int pthread_condattr_destroy(pthread_condattr_t* attr);
//返回值:成功返回0;失败返回错误编码
** 进程共享属性的设置与获取(pshared)
#include <pthread.h>
int pthread_condattr_setshared(pthread_condattr_t* attr,int pshared);
int pthread_condattr_getshared(const pthread_condattr_t* restrict attr,int* restrict pshared);
//返回值:成功返回0;失败返回错误编码
** 时钟属性的设置与获取(clock)
#include <pthread.h>
int pthread_condattr_setclock(pthread_condattr_t* attr,clockid_t clock_id);
int pthread_condattr_getclock(const pthread_condattr_t* restrict attr,clockid_t *restrict clock_id);
//返回值:成功返回0;失败返回错误编码
屏障属性
屏障属性结构体(pthread_barrierattr_t
)
**屏障属性结构体的初始化
#include <pthread.h>
int pthread_barrierattr_init(pthread_barrierattr_t* attr);
int pthread_barrierattr_destroy(pthread_barrierattr_t* attr);
//返回值:成功返回0;失败返回错误编码
**进程共享属性的设置与获取(pshared)
#include <pthread.h>
int pthread_barrierattr_setshared(pthread_barrierattr_t* attr,int pshared);
int pthread_barrierattr_getshared(const pthread_barrierattr_t* restrict attr,int* restrict pshared);
//返回值:成功返回0;失败返回错误编码