pthread库学习
来源:互联网 发布:广东移动网络测速平台 编辑:程序博客网 时间:2024/06/05 20:45
1.pthread_create 创建线程发生内存分配不足错误,通常是线程数过多。自已机子ubuntu8.04能成功创建线程大小为382。
为了能创建更多线程,第一条路是创建多进程,第二条路是减少线程栈的大小。
通常线程栈的大小受制于两个因素:
其一栈的最小值,通过宏PTHREAD_STACK_MIN可能得到大小,我的机子为16384即16k,任何线程不能小于此值,而且这个值没有考虑线程的具体逻辑,仅仅启动线程所需的大小。通常线程还要局部变量,线程大小应该比它大。
其二系统限制栈最大值,可以通过ulimit -s系统命令,得到本系统的最大值,我的机子为8192即8M,同时任何线程不能超过此值(可以利用ulimit -s xxx,修改成xxx值,单位为k)。
利用pthread_create创建线程时,pthread库会自动地为线程设定栈大小,我们通常不用明显地指定。当发生了内存分配不足时,就必须我们自已动手来指定栈大小。
pthread库用pthread_attr_t类型变量,来操纵线程属性。我们可以利用pthread_attr_getstacksize来得到默认分配大小,注意到必须先调用pthread_attr_init初始化函数,才能得到正确的值,否则
得到的值是不正确的。
示例代码:
pthread_attr_t attr;
pthread_attr_init(&attr);
std::size_t stack_size;
pthread_attr_getstacksize(&attr, &stack_size);
我的机子上是8388608即8192K即8M。
为什么系统有一个限制栈最大值呢?因为现在我们的cpu位数有限,例如我的32位,则cpu的寻址空间为4G,因此每一个进程的空间为4G。因为进程需要操作系统的支持,需要划分一部分空间给进入操作系统内核时候
使用,称之为内核态。例如需要系统调用,需要内核栈存放数据,需要同步通信数据等等。在不同的操作系统中划分的空间是不太相同的,linux下一般为1G,windows系统下一般2G。
进程去除内核态占用的空间外,就是用户态的空间了。
用户态空间划分成代码段,数据段,栈段。其中在linux中代码段分配在低地址,只读的。接下来是数据段,数据段细划分为全局(已初始化)静态(已初始化)数据
区,常量区,全局(未初始化)静态(未初始化)区。接下来就是栈空间了,但是栈空间访问方式与其它段不相同,栈分配空间是从高到低(通过esp先指向高地址,然后减去相应大小数据,达到分配空间的目的)。
因为一般情况下,数据段最后一个地址与栈的esp指向的地址存在相大的空间,这些空间就可以让我们做一些事情。可以利用这些空间动态地分配,称之为堆,可以利用这些空间分配给线程,称之为线程栈。
如何得到这段空间的起始地址呢?在linux下存在一个系统调用system_brk,给此函数传0作为参数,其返回值就是起始地址。
通常进程的用户态空间中我们可以自由控制的只有这段空间。linux下这段空间的大小一般为3000M左右(当然如果程序代码量较大,会更少),而用户态空间总共3G(3072M)大小。
因为创建线程栈中也只有在这段空间,所以系统要在数量和大小做一个平衡,因此存在一个栈最大值。
如何确定线程栈的大小呢?主要看线程函数中用的局部变量多少,动态申请空间的不算(但也会间接影响到线程数量的),特别要引起注意的是线程函数中代码不算,不要看线程函数代码非常多,就以为线程函数代码会占很多栈空间,前面说过,代码是放在代码段的,同理会间接影响到线程数量。因为总空间即用户空间有限,当代码段增大,数据段增大,自然自由空间就会减少。如果程序代码中使用了堆的话,还要去掉堆的空间。
所以在栈最小值基础上加上相应局部变量空间,再适当地增加一些空间(为安全起见)就可以了。
以前是个人参考各种资料理解总结而成的,并不代表一定是对的,欢迎有朋友指正。
2.利用pthread_cond_t类型变量实现条件通信,关键在于理解pthread_cond_wait函数,也是灵活运用条件通信的关键。
pthread_cond_wait需要二个参数,一个是条件变量地址,一个是mutex型变量地址。第一个参数很好理解,因为需要等待条件变量变化,所以需要它地址。
第二个参数却不易理解,明明我使用条件变量通信与mutex有什么关系,为什么需要它呢?看起来是多此一举,把问题复杂化了。
呵呵,我自已用sem操作来模拟没有mutex的条件变量,结果很惨,具体代码不好意思拿出来了,主要问题出在没办法确保sem的顺序。
假设a线程专门通过sem_post来实现点灯,通知资源可用。
假设b线程专门通过sem_wait来实现等待灯亮,并且消费资源和灭灯。
a,b两个线程,独立运行,推进速度未知,看起来,好像实现同步。假设b线程足够快,a线程慢一点,应该没多大问题。如果b线程非常慢,a线程非常快的话,有可能会产生两个问题:
1。资源未被消费,却被新资源刷新,重复点灯。
2。读“脏数据”,即当b线程消费了一部分资源,被切换成a线程,a线程用新资源刷新,当再切换回b线程时,接下来消费资源就是新资源,与上次消费资源不同步,如果b线程消费资源
与整个资源相关的,就会产生错误的结果。
所以类似这种问题,需要一个mutex来保证当正在消费资源或者产生新资源的独占性。
所以也就知道为什么条件变量通信需要mutex支持。
再来看pthread_cond_wait具体逻辑,它先释放mutex锁,然后等待信号,如果有信号通知,它重新获得mutex锁,并返回。
因为pthread_cond_wait先要释放锁,所以在它调用之前,一定要先获得锁,否则谈不上释放锁。
至于pthread_cond_wait返回后,要不要释放锁,则看具体的逻辑代码需要,一般情况下是需要的。
需要引起注意的是,当pthread_cond_wait返回的时候,并一定代表所求条件成立,强烈建议重新检查。
综上所述,使用pthread_cond_wait的示例代码为:
pthread_mutex_lock(&mutex);
while (!is_my_need)
{
pthread_cond_wait(&cond, &mutex);
}
pthread_mutex_unlock(&mutex);
与pthread_cond_wait配合使用的函数为pthread_cond_signal, pthread_cond_broadcast函数。
3.pthread_create创建线程出现“Resource temporarily unavailable”错误时,表示线程创建过多,至于如何修改,我暂时还没有找到解决的办法。
有人说要用pthread_detach分离,但是我试过了,我的测试程序没通过。
为了能创建更多线程,第一条路是创建多进程,第二条路是减少线程栈的大小。
通常线程栈的大小受制于两个因素:
其一栈的最小值,通过宏PTHREAD_STACK_MIN可能得到大小,我的机子为16384即16k,任何线程不能小于此值,而且这个值没有考虑线程的具体逻辑,仅仅启动线程所需的大小。通常线程还要局部变量,线程大小应该比它大。
其二系统限制栈最大值,可以通过ulimit -s系统命令,得到本系统的最大值,我的机子为8192即8M,同时任何线程不能超过此值(可以利用ulimit -s xxx,修改成xxx值,单位为k)。
利用pthread_create创建线程时,pthread库会自动地为线程设定栈大小,我们通常不用明显地指定。当发生了内存分配不足时,就必须我们自已动手来指定栈大小。
pthread库用pthread_attr_t类型变量,来操纵线程属性。我们可以利用pthread_attr_getstacksize来得到默认分配大小,注意到必须先调用pthread_attr_init初始化函数,才能得到正确的值,否则
得到的值是不正确的。
示例代码:
pthread_attr_t attr;
pthread_attr_init(&attr);
std::size_t stack_size;
pthread_attr_getstacksize(&attr, &stack_size);
我的机子上是8388608即8192K即8M。
为什么系统有一个限制栈最大值呢?因为现在我们的cpu位数有限,例如我的32位,则cpu的寻址空间为4G,因此每一个进程的空间为4G。因为进程需要操作系统的支持,需要划分一部分空间给进入操作系统内核时候
使用,称之为内核态。例如需要系统调用,需要内核栈存放数据,需要同步通信数据等等。在不同的操作系统中划分的空间是不太相同的,linux下一般为1G,windows系统下一般2G。
进程去除内核态占用的空间外,就是用户态的空间了。
用户态空间划分成代码段,数据段,栈段。其中在linux中代码段分配在低地址,只读的。接下来是数据段,数据段细划分为全局(已初始化)静态(已初始化)数据
区,常量区,全局(未初始化)静态(未初始化)区。接下来就是栈空间了,但是栈空间访问方式与其它段不相同,栈分配空间是从高到低(通过esp先指向高地址,然后减去相应大小数据,达到分配空间的目的)。
因为一般情况下,数据段最后一个地址与栈的esp指向的地址存在相大的空间,这些空间就可以让我们做一些事情。可以利用这些空间动态地分配,称之为堆,可以利用这些空间分配给线程,称之为线程栈。
如何得到这段空间的起始地址呢?在linux下存在一个系统调用system_brk,给此函数传0作为参数,其返回值就是起始地址。
通常进程的用户态空间中我们可以自由控制的只有这段空间。linux下这段空间的大小一般为3000M左右(当然如果程序代码量较大,会更少),而用户态空间总共3G(3072M)大小。
因为创建线程栈中也只有在这段空间,所以系统要在数量和大小做一个平衡,因此存在一个栈最大值。
如何确定线程栈的大小呢?主要看线程函数中用的局部变量多少,动态申请空间的不算(但也会间接影响到线程数量的),特别要引起注意的是线程函数中代码不算,不要看线程函数代码非常多,就以为线程函数代码会占很多栈空间,前面说过,代码是放在代码段的,同理会间接影响到线程数量。因为总空间即用户空间有限,当代码段增大,数据段增大,自然自由空间就会减少。如果程序代码中使用了堆的话,还要去掉堆的空间。
所以在栈最小值基础上加上相应局部变量空间,再适当地增加一些空间(为安全起见)就可以了。
以前是个人参考各种资料理解总结而成的,并不代表一定是对的,欢迎有朋友指正。
2.利用pthread_cond_t类型变量实现条件通信,关键在于理解pthread_cond_wait函数,也是灵活运用条件通信的关键。
pthread_cond_wait需要二个参数,一个是条件变量地址,一个是mutex型变量地址。第一个参数很好理解,因为需要等待条件变量变化,所以需要它地址。
第二个参数却不易理解,明明我使用条件变量通信与mutex有什么关系,为什么需要它呢?看起来是多此一举,把问题复杂化了。
呵呵,我自已用sem操作来模拟没有mutex的条件变量,结果很惨,具体代码不好意思拿出来了,主要问题出在没办法确保sem的顺序。
假设a线程专门通过sem_post来实现点灯,通知资源可用。
假设b线程专门通过sem_wait来实现等待灯亮,并且消费资源和灭灯。
a,b两个线程,独立运行,推进速度未知,看起来,好像实现同步。假设b线程足够快,a线程慢一点,应该没多大问题。如果b线程非常慢,a线程非常快的话,有可能会产生两个问题:
1。资源未被消费,却被新资源刷新,重复点灯。
2。读“脏数据”,即当b线程消费了一部分资源,被切换成a线程,a线程用新资源刷新,当再切换回b线程时,接下来消费资源就是新资源,与上次消费资源不同步,如果b线程消费资源
与整个资源相关的,就会产生错误的结果。
所以类似这种问题,需要一个mutex来保证当正在消费资源或者产生新资源的独占性。
所以也就知道为什么条件变量通信需要mutex支持。
再来看pthread_cond_wait具体逻辑,它先释放mutex锁,然后等待信号,如果有信号通知,它重新获得mutex锁,并返回。
因为pthread_cond_wait先要释放锁,所以在它调用之前,一定要先获得锁,否则谈不上释放锁。
至于pthread_cond_wait返回后,要不要释放锁,则看具体的逻辑代码需要,一般情况下是需要的。
需要引起注意的是,当pthread_cond_wait返回的时候,并一定代表所求条件成立,强烈建议重新检查。
综上所述,使用pthread_cond_wait的示例代码为:
pthread_mutex_lock(&mutex);
while (!is_my_need)
{
pthread_cond_wait(&cond, &mutex);
}
pthread_mutex_unlock(&mutex);
与pthread_cond_wait配合使用的函数为pthread_cond_signal, pthread_cond_broadcast函数。
3.pthread_create创建线程出现“Resource temporarily unavailable”错误时,表示线程创建过多,至于如何修改,我暂时还没有找到解决的办法。
有人说要用pthread_detach分离,但是我试过了,我的测试程序没通过。
- pthread库学习
- pthread库学习-4 : 互斥量
- pthread 学习
- pthread学习
- pthread学习
- pthread学习
- pthread库学习(1): 线程的创建
- pthread库学习-2:基本函数
- pthread库学习-3:线程属性
- Linux 多线程编程(Pthread 库)学习笔记
- pthread 学习总结
- Pthread学习完毕
- pthread学习笔记
- pthread学习笔记
- pthread 学习笔记
- linux pthread线程学习
- [Linux]pthread学习笔记
- Pthread 学习(1)
- 规划索引
- 九月六日 多云
- 探讨C++中的引用和指针
- 软件企业成长的烦恼――多个并行软件项目研发管理策略(1)--成长烦恼
- 谷歌产品经理揭秘Chrome背后的故事
- pthread库学习
- 查找TCP连接状态
- 鼠标拖曳实现svg矩形的任意切分
- spi gpio flash uart pcmcia
- 高效分頁存儲過程
- 理发师悖论与集合
- Linux Oracle 这学期的课
- 我的数据库代码
- BLL,IDAL,MODEL,UI,DBUtility,MSSQLServerService,Factory