pthread_create可以创build的最大线程数是多less?

可能重复:
通过pthread_create线程创build相同的内核线程?

我使用下面的代码来testingpthread_create函数可以创build的最大线程数。

#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函数可以创build的线程的最大数量吗?

此外,我使用下面的命令查看我的系统允许的最大线程数:

 # cat /proc/sys/kernel/threads-max 

号码是772432。

为什么我的程序的输出不等于threads-max的值?

我的操作系统是Fodaro 16,有12个内核,48G RAM。

每个线程堆栈的默认大小是在测试中人为施加的限制。 虽然给予进程的默认堆栈(初始线程)根据需要动态增长,但其他线程的堆栈大小是固定的。 默认的大小通常是非常大的,比如两兆字节,以确保每个线程的堆栈足够大,甚至病态的情况下(深递归等)。

在大多数情况下,线程工作者只需要很少的堆栈。 我发现在我使用的所有体系结构中,只要不使用深度递归算法或大型局部变量(结构体或数组),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)整除。 由于页面大小是所有架构的两倍,因此使用足够大的二次幂应始终有效。

另外,我还在那里添加了一个修复程序。 你只尝试加入一个不存在的线程(循环试图创建的线程,但失败),但是你需要加入所有线程(以确保它们都完成了他们的工作)。

进一步推荐的修复:

而不是使用睡眠,使用条件变量。 让每个线程都等待条件变量( pthread_cond_wait() )(同时持有互斥锁),然后释放互斥锁并退出。 这样,你的主函数只需要在条件变量上广播( pthread_cond_broadcast() )来告诉现在它们可以退出的所有线程,然后它就可以加入每一个线程,并且你可以确定这个线程数量确实并发运行。 当你的代码现在,一些线程可能有足够的时间从睡眠中醒来并退出。

理论上,进程可以拥有的线程数量没有限制。 但实际限制可能来自于所有线程共享资源的事实。

这意味着,在某些情况下,例如,由于缺乏与这种堆栈空间共享的资源,进程不能创建超过一定数量的进程。

根据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 (打印/设置最大用户进程)获得的限制值相同。