创建线程时受两个因素限制:
1. 该操作系统最大虚拟内存:
每创建一个线程,系统需要在虚拟内存中分配一个栈空间,随着创建的线程数量增加,系统虚拟内存逐渐被占满,则再也无法创建。
在进程里创建一个线程需要消耗多少虚拟内存大小?
我们可以执行 ulimit -a 这条命令,查看进程创建线程时默认分配的栈空间大小,比如我这台服务器默认分配给线程的栈空间大小为 8M。
2. 系统参数设限:
Linux 并没有内核参数来控制单个进程创建的最大线程个数,但是有系统级别的参数来控制整个系统的最大线程个数。
这个问题由不同位数的操作系统(32位、64位系统)分情况讨论:
在LInux 的操作系统中,虚拟地址空间由 内核空间 用户空间 两部分组成,而不同位数的操作系统,地址空间范围不同,如下:
32位系统:
内核空间 1G
用户空间(可使用空间)3G
假设创建一个线程需要占用 10M 虚拟内存,总共有 3G 虚拟内存可以使用,这种情况可以创建多少个线程呢?
代码测试一下:
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<stdlib.h>
void* thread(void*arg)
{
printf("creat one thread success!\n");
}
int main()
{
int res=0;
int count=0;
pthread_t id;
while(res==0)
{
res=pthread_create(&id,NULL,thread,NULL);
count++;
printf("count=%d\n",count);
}
exit(0);
}
最后的结果由运行输出的count数目为准
64位系统:
用户空间的虚拟内存最大值是 128T,如果按创建一个线程需占用 10M 栈空间的情况来算,那么理论上,可以创建 128T/10M 个线程,也就是 1000多万个线程?
事实上,肯定创建不了那么多线程,除了虚拟内存的限制,还有系统的限制。
这三个内核参数_创建线程的上限:
- /proc/sys/kernel/threads-max,表示系统支持的最大线程数,默认值是 14553;
可以通过 top -H 查看:
通过以下代码,将 threads-max 参数设置成 99999:
echo 99999 > /proc/sys/kernel/threads-max
- /proc/sys/kernel/pid_max,表示系统全局的 PID 号数值的限制,每一个进程或线程都有 ID,ID 的值超过这个数,进程或线程就会创建失败,默认值是 32768;
通过以下代码,将pid_max 参数设置成 99999:
echo 99999 > /proc/sys/kernel//pid_max
- /proc/sys/vm/max_map_count,表示限制一个进程可以拥有的VMA(虚拟内存区域)的数量,创建线程所占用的栈累计空间超过VMA,也会导致创建线程失败,默认值是 65530。
通过以下代码,将 max_map_count 参数设置成 99999:
echo 99999 > /proc/sys/kernel/max_map_count
总结:
- 32 位系统,用户态的虚拟空间只有 3G,如果创建线程时分配的栈空间是 10M,那么一个进程最多只能创建 300 个左右的线程。
- 64 位系统,用户态的虚拟空间大到有 128T,理论上不会受虚拟内存大小的限制,而会受系统的参数或性能限制。