文章目录
1. 系统限制:线程限制
用户关心的系统限制可能有:
- 系统限制:线程栈最大 最小值
- 系统限制:一个进程可以创建的最大线程值
sysconf函数用来提供接口,但是因为POSIX标准并没有规定相关宏(因此兼容性不佳,这里不再列举sysconf参数)
2. 线程属性
用户关系的线程属性可能有:
- detach 与 joinable :决定系统回收线程资源的时机
- 线程栈地址与大小:用户对于线程栈可能有自己的考虑
- 可取消状态与不可取消状态:线程是否可被对等线程终止
- 警戒缓冲区:用来防止线程栈溢出
- 并发度:用户可能对于线程模型有自己的考虑
2.1 分离汇合属性
接口:
/*设置attr中detachstate*/
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
/*获取attr中detachstate*/
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);
CONFORMING TO
POSIX.1-2001, POSIX.1-2008.
举例:
#include <iostream>
using namespace std;
extern "C"
{
#include <unistd.h>
#include <pthread.h>
}
void* fool(void *)
{
int oldcancelstate = 0;
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,&oldcancelstate);
while(1)
{
cout << "fool thread" << endl;
sleep(1);
}
}
int main(void)
{
pthread_t thread1;
pthread_attr_t attr;
if(pthread_attr_init(&attr) != 0)
{
cout << "init attr failed" << endl;
return -1;
}
/*PTHREAD_CREATE_DETACHED or PTHREAD_CREATE_JOINABLE */
if(pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE) != 0)
{
cout << "set detach failed" << endl;
return -1;
}
int detach;
if(pthread_attr_getdetachstate(&attr,&detach) != 0)
{
cout << "get detach failed" << endl;
return -1;
}
cout << "Detach state: " << detach << endl;
pthread_create(&thread1,&attr,fool,NULL);
sleep(2);
pthread_cancel(thread1);
if(pthread_attr_destroy(&attr) != 0)
{
cout << "attr destroy failed" << endl;
return -1;
}
return 0;
}
2.2 线程栈地址与大小
2.2.1 线程栈由pthread_create默认分配
线程栈 addr = NULL,size =0 ;表示线程栈由pthread_create 默认分配
#include <iostream>
using namespace std;
extern "C"
{
#include <unistd.h>
#include <pthread.h>
}
void* fool(void *)
{
int oldcancelstate = 0;
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,&oldcancelstate);
while(1)
{
cout << "fool thread" << endl;
sleep(1);
}
}
int main(void)
{
pthread_t thread1;
pthread_attr_t attr;
if(pthread_attr_init(&attr) != 0)
{
cout << "init attr failed" << endl;
return -1;
}
void *addr;
size_t stacksize;
/*PTHREAD_CREATE_DETACHED or PTHREAD_CREATE_JOINABLE */
if(pthread_attr_getstack(&attr,&addr,&stacksize) != 0)
{
cout << "set detach failed" << endl;
return -1;
}
cout << "stack addr: " << addr
<< " stack size: " << stacksize << endl;
pthread_create(&thread1,&attr,fool,NULL);
sleep(2);
pthread_cancel(thread1);
if(pthread_attr_destroy(&attr) != 0)
{
cout << "attr destroy failed" << endl;
return -1;
}
return 0;
}
2.2.2 只设置线程栈大小
接口:
/*设置attr中栈值为stacksize*/
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
/*获取attr中栈值给stacksize*/
int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize);
CONFORMING TO
POSIX.1-2001, POSIX.1-2008.
pthread_attr_setstacksize 自动分配内存
#include <iostream>
using namespace std;
extern "C"
{
#include <unistd.h>
#include <pthread.h>
#include <sys/mman.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
}
void* fool(void *)
{
int oldcancelstate = 0;
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,&oldcancelstate);
while(1)
{
cout << "fool thread" << endl;
sleep(1);
}
}
int main(void)
{
pthread_t thread1;
pthread_attr_t attr;
if(pthread_attr_init(&attr) != 0)
{
cout << "init attr failed" << endl;
return -1;
}
void *addr;
size_t stacksize;
if(pthread_attr_setstacksize(&attr,16384) != 0)
{
cout << "set stacksize failed" << endl;
return -1;
}
if(pthread_attr_getstack(&attr,&addr,&stacksize) != 0)
{
cout << "set detach failed" << endl;
return -1;
}
cout << "stack addr: " << addr
<< " stack size: " << stacksize << endl;
pthread_create(&thread1,&attr,fool,NULL);
sleep(2);
pthread_cancel(thread1);
if(pthread_attr_destroy(&attr) != 0)
{
cout << "attr destroy failed" << endl;
return -1;
}
return 0;
}
输出:stack addr: 0xffffffffffffc000 stack size: 16384
2.2.3 设置线程栈地址与大小
接口:
/*设置attr中栈地址以及size*/
int pthread_attr_setstack(pthread_attr_t *attr,
void *stackaddr, size_t stacksize);
/*获取attr中栈地址以及size*/
int pthread_attr_getstack(const pthread_attr_t *attr,
void **stackaddr, size_t *stacksize);
CONFORMING TO
POSIX.1-2001, POSIX.1-2008.
用户自己分配内存:
#include <iostream>
using namespace std;
extern "C"
{
#include <unistd.h>
#include <pthread.h>
#include <sys/mman.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
}
void* fool(void *)
{
int oldcancelstate = 0;
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,&oldcancelstate);
while(1)
{
cout << "fool thread" << endl;
sleep(1);
}
}
int main(void)
{
pthread_t thread1;
pthread_attr_t attr;
if(pthread_attr_init(&attr) != 0)
{
cout << "init attr failed" << endl;
return -1;
}
void* addr=mmap(NULL,16384,PROT_EXEC | PROT_READ | PROT_WRITE,MAP_PRIVATE |MAP_ANONYMOUS ,-1,0);
if(MAP_FAILED == addr)
{
cout << "mmap failed" << endl;
return -1;
}
size_t stacksize;
if(pthread_attr_setstack(&attr,addr,16384) != 0)
{
cout << "set stacksize failed" << endl;
return -1;
}
if(pthread_attr_getstack(&attr,&addr,&stacksize) != 0)
{
cout << "set detach failed" << endl;
return -1;
}
cout << "stack addr: " << addr
<< " stack size: " << stacksize << endl;
pthread_create(&thread1,&attr,fool,NULL);
sleep(2);
pthread_cancel(thread1);
if(pthread_attr_destroy(&attr) != 0)
{
cout << "attr destroy failed" << endl;
return -1;
}
return 0;
}
2.3 可终止与不可终止状态
接口:
#include <pthread.h>
/*可以被终止或者不可被终止*/
int pthread_setcancelstate(int state, int *oldstate
/*立即终止还是延迟终止*/
int pthread_setcanceltype(int type, int *oldtype);
举例:略
2.4 警戒缓冲
接口:
#include <pthread.h>
int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);
int pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize);
举例:
上文修改线程栈addr函数,pthread_attr_t size字段为0,表示不使用警戒缓冲。(换言之,用户指定线程栈addr与guard size是互斥使用的)
#include <iostream>
using namespace std;
extern "C"
{
#include <unistd.h>
#include <pthread.h>
#include <sys/mman.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
}
void* fool(void *)
{
int oldcancelstate = 0;
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,&oldcancelstate);
while(1)
{
cout << "fool thread" << endl;
sleep(1);
}
}
int main(void)
{
pthread_t thread1;
pthread_attr_t attr;
if(pthread_attr_init(&attr) != 0)
{
cout << "init attr failed" << endl;
return -1;
}
size_t guardsize;
if(0 != pthread_attr_getguardsize(&attr,&guardsize))
{
cout << "get guardsize failed" << endl;
return -1;
}
cout << "guardsize = " << guardsize << endl;
pthread_create(&thread1,&attr,fool,NULL);
sleep(2);
pthread_cancel(thread1);
if(pthread_attr_destroy(&attr) != 0)
{
cout << "attr destroy failed" << endl;
return -1;
}
return 0;
}
2.5 线程模型选择:并发度考虑
用户线程与内核线程大体上有两种类型:
-
一对一映射
每一个用户线程在内核中都有一个task结构表示,每一个用户线程相当于一个轻量级进程(优势便于发挥多处理器性能) -
多对一映射
多个用户线程在内核中只有一个task结构表示,任务切换通过用户层完成。优点是可以几乎无限制的创建用户线程
缺点:任何用户线程阻塞会造成其他线程阻塞!
接口:
#include <pthread.h>
/*可以这样去提示系统,但是不保证真的生效*/
int pthread_setconcurrency(int new_level);
/*0 表示系统决定并发模型,其它表示用户曾尝试指定并发模型*/
int pthread_getconcurrency(void);