线程属性
线程属性初始化
【注意】应先初始化线程属性,再创建线程
- 初始化线程属性
int pthread_attr_init(pthread_attr_t *attr); 成功:0;失败:错误号
- 销毁线程属性所占用的资源
int pthread_attr_destroy(pthread_attr_t *attr); 成功:0;失败:错误号
pthread_attr_t结构体
主要的结构体成员:
- 线程分离状态
- 线程栈的大小(默认平均分配)
查看栈空间:ulimit -a --> stack size 8192kbytes(一个进程)线程均分8192kbytes - 线程栈警戒缓冲区大小(位于栈末尾)
- 警戒区示意图
设置线程分离
- 设置线程属性,分离 or 非分离
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
- 获取线程属性,分离 or 非分离
int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate);
参数:
- attr:已初始化的线程属性
- detachstate:PTHREAD_CREATE_DETACHED(分离线程)
PTHREAD_CREATE_JOINABLE(非分离)
- 演示线程分离
- 演示线程不分离
【问题】如果一个线程为分离线程,而这个线程运行又非常快,它很可能再pthread_create函数返回之前就终止了,它终止以后就可能将线程号和系统资源移交给其他的线程使用,这样调用pthread_create的线程就得到了错误的线程号。
【解决】可以采取一定的同步措施,最简单的方法之一是可以在被创建的线程函数中调用pthread_cond_timedwait函数,让线程等待一会儿,留出足够的时间让函数pthread_create返回。设置一段等待时间,是在多线程编程里常用的方法。但是注意不要使用wait()之类的函数,它们是使整个进程睡眠,并不能解决线程同步的问题
设置线程栈大小
- 设置线程栈大小
int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, size_t stacksize);
- 获取线程栈大小
int pthread_attr_getstack(pthread_attr_t *attr, void *stackaddr, size_t *stacksize);
参数:
- attr:指向一个线程属性的指针
- stackaddr:返回获取的栈地址
- stacksize:返回获取的栈大小
【思考】编写一个程序,查看当前机器默认一个最多能够创建多少个线程
NPTL
本地POSIX线程库
- 查看当前pthread库版本getconf GNU_LIBPTHREAD_VERSION
- NPTL实现机制(POSIX)
- 使用线程库时gcc指定 -lpthread
线程使用注意事项
- 主线程退出其他线程不退出,主线程应调用pthread_exit
- 避免僵尸线程
- malloc和mmap申请的内存可以被其他线程释放(同一进程的子线程间共享地址空间)
- 应避免在多线程模型中调用fork。除非马上exec,子进程中只有调用fork的线程存在,其他线程在子进程中均pthread_exit
- 信号的复杂语义很难喝多线程共存,应避免在多线程引入信号机制