红联Linux门户
Linux帮助

Linux的线程创建限制

发布时间:2016-12-12 09:38:56来源:linux网站作者:delphiwcdj
现网有个版本上线一段时间后,通过SSH重新登陆时显示Cannot allocate memory错误,结果只能通过重启机器来恢复服务。通过分析发现是新的版本引入一个bug,某个进程会不停地创建新的线程,那么问题是Linux下一个进程可以创建多少个线程,从而会导致这个错误出现。
 
原因分析
问题重现,通过一个测试程序,验证错误是否会重现。
#include <iostream>
#include <pthread.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
using namespace std;
void* thr_func (void*)
{
for(;;) sleep(500);
return 0;
}
void max_thread_test ()
{
const int MAX = 4194304;
//const int MAX = 10;
for (int i = 0; i < MAX; ++i) {
int ret = 0;
if (!(i % (MAX / 100))) std::cerr << "..." << i;
pthread_attr_t attr;
pthread_attr_init(&attr);
// detached
ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (ret) { 
perror("pthread_attr_setdetachstate err"); 
exit(1);
};
// thread stacksize
int stacksize = 16384;
pthread_attr_setstacksize(&attr, stacksize);
if (ret) { 
perror("pthread_attr_setstacksize err"); 
exit(1);
};
pthread_t thread;
ret = pthread_create(&thread, &attr, thr_func, NULL);
if (ret) {
std::cerr << "threads created " << i << std::endl ;
perror("pthread_create");
exit(1);
}
}
std::cerr << std::endl;
std::cout << "exit (succes)" << std::endl;
}
int main()
{
max_thread_test();
for(;;) sleep(5000);
std::cout << "end" << std::endl;
return 0;
}
/* 
执行后会出现类似下面的错误。
$./test_max_thread 
...0threads created 2047
pthread_create: Cannot allocate memory
*/
除了内存大小限制外,还有很多内核参数的限制,但理论上一个进程可以创建的最大线程数量为:
number of threads = total virtual memory / (stack size*1024*1024)
因此,32位系统由于进程的虚拟地址空间为4G,可以创建的线程数量为3G/8M=384个线程,而64位系统的进程可以创建的线程数量为128T/8M=16777216个线程(千万级)。当然在实际使用中一般不会创建这么多线程,因为线程间的切换会占用2000+的CPU时钟周期,可能导致CPU过高。一般会根据CPU核数启用相应的线程数,尽量减少不必要的线程切换。
Linux的线程创建限制
通过修改下面的参数,可以尽可能地创建更多的线程。
echo 1 > /proc/sys/vm/overcommit_memory 
echo 1000000 > /proc/sys/kernel/threads-max
echo 10000000 > /proc/sys/vm/max_map_count
echo "4194304" > /proc/sys/kernel/pid_max
 
参考
理解Linux的memory overcommit:http://www.linuxdiyf.com/linux/26821.html
 
本文永久更新地址:http://www.linuxdiyf.com/linux/26822.html