可能重复:
The thread create by pthread_create the same with the kernel thread?
我使用下面的代码来测试pthread_create函数可以创建的最大线程数。
#include <pthread.h>
#include <stdio.h>
static unsigned long long thread_nr = 0;
pthread_mutex_t mutex_;
void* inc_thread_nr(void* arg) {
(void*)arg;
pthread_mutex_lock(&mutex_);
thread_nr ++;
pthread_mutex_unlock(&mutex_);
/* printf("thread_nr = %d\n", thread_nr); */
sleep(300000);
}
int main(int argc, char *argv[])
{
int err;
int cnt = 0;
pthread_t pid[1000000];
pthread_mutex_init(&mutex_, NULL);
while (cnt < 1000000) {
err = pthread_create(&pid[cnt], NULL, (void*)inc_thread_nr, NULL);
if (err != 0) {
break;
}
cnt++;
}
pthread_join(pid[cnt], NULL);
pthread_mutex_destroy(&mutex_);
printf("Maximum number of threads per process is = %d\n", thread_nr);
}
输出是:
Maximum number of threads per process is = 825
这是pthread_create函数可以创建的最大线程数吗?
此外,我使用以下命令查看我的系统允许的最大线程数:
# cat /proc/sys/kernel/threads-max
这个数字是772432。
为什么我的程序输出不等于threads-max
的值?
我的操作系统是Fodaro 16,有12个核心,48G RAM。
答案 0 :(得分:8)
每个线程堆栈的默认大小是人为地在测试中强加限制。虽然给予进程的默认堆栈(初始线程)会根据需要动态增长,但其他线程的堆栈大小是固定的。默认大小通常非常大,类似于2兆字节,以确保每个线程堆栈足够大,甚至可以用于病理情况(深度递归等)。
在大多数情况下,线程工作者只需要很少的堆栈。我发现在我使用的所有体系结构中,每个线程堆栈64k(65536字节)就足够了,只要我不使用深度递归算法或大型局部变量(结构或数组)。
要显式指定每线程堆栈大小,请将main()
修改为以下内容:
#define MAXTHREADS 1000000
#define THREADSTACK 65536
int main(int argc, char *argv[])
{
pthread_t pid[MAXTHREADS];
pthread_attr_t attrs;
int err, i;
int cnt = 0;
pthread_attr_init(&attrs);
pthread_attr_setstacksize(&attrs, THREADSTACK);
pthread_mutex_init(&mutex_, NULL);
for (cnt = 0; cnt < MAXTHREADS; cnt++) {
err = pthread_create(&pid[cnt], &attrs, (void*)inc_thread_nr, NULL);
if (err != 0)
break;
}
pthread_attr_destroy(&attrs);
for (i = 0; i < cnt; i++)
pthread_join(pid[i], NULL);
pthread_mutex_destroy(&mutex_);
printf("Maximum number of threads per process is %d (%d)\n", cnt, thread_nr);
}
请注意attrs
电话不会使用pthread_create()
。可以认为线程属性更像是pthread_create()
应该如何创建线程的模板; 它们不是赋予线程的属性。这让许多有抱负的pthreads程序员兴奋不已,所以这是你最好从入手处获得的东西之一。
关于堆栈大小本身,它必须至少为PTHREAD_STACK_MIN
(在Linux中为16384,我相信)并且可以被sysconf(_SC_PAGESIZE)
整除。由于页面大小在所有体系结构上都是2的幂,因此使用足够大的2的幂应始终有效。
另外,我也在那里添加了修复程序。您只尝试加入一个不存在的线程(循环尝试创建但未通过的线程),但您需要加入所有这些线程(以确保它们都完成了它们的工作)。
进一步推荐的修复:
使用条件变量而不是使用睡眠。让每个线程在条件变量上等待(pthread_cond_wait()
)(同时按住互斥锁),然后释放互斥锁并退出。这样你的主要功能只需要在条件变量上广播(pthread_cond_broadcast()
)来告诉他们现在可以退出的所有线程,然后它就可以加入每个线程,你可以确定这个线程的数量真正同时运行。正如您的代码现在所处,某些线程可能有足够的时间从睡眠状态唤醒并退出。
答案 1 :(得分:4)
理论上,进程可以拥有的线程数没有限制。但实际限制可能来自所有线程共享资源的事实。
这意味着,在某些时候,由于缺少与此类堆栈空间共享的资源,流程无法创建超过一定数量的流程。
答案 2 :(得分:2)
根据pthread_create(3)
手册页,还有另一个限制:
RLIMIT_NPROC soft resource limit (set via setrlimit(2)), which limits the number
of process for a real user ID.
尝试使用getrlimit(2)
查找此限制的值。如果该值仍然与您测量的数字不匹配(825),请尝试使用setrlimit(2)
更改此限制,以验证它是否会影响您的测量值。
编辑:实际上,RLIMIT_NPROC限制值与使用shell命令ulimit -u
(打印/设置最大用户进程)获得的值相同。