当前位置 博文首页 > $firecat全宏的代码足迹$:一个进程(Process)最多可以生成多少个

    $firecat全宏的代码足迹$:一个进程(Process)最多可以生成多少个

    作者:[db:作者] 时间:2021-07-28 17:52

    一、Windows版本

    文章来源:http://blog.csdn.net/great3779/article/details/5930190

    1.进程中创建线程的限制

    默认情况下,一个线程的栈要预留1M的内存空间,而一个进程中可用的内存空间只有2G,所以理论上一个进程中最多可以开2048个线程,但是内存当然不可能完全拿来作线程的栈,所以实际数目要比这个值要小。

    ?

    ?

    [cpp]?view plaincopy

    1. #include?"stdafx.h"??
    2. #include?<windows.h>??
    3. #include?<process.h>??
    4. #include?<assert.h>??
    5. ??
    6. volatile?bool?gbExitThread?=?false;??
    7. HANDLE?ghDataEvent?=?CreateEvent(NULL,?FALSE,?FALSE,?NULL);??
    8. ??
    9. UINT?WINAPI?SubThread(void*?ptr)??
    10. {??
    11. ????int?nThreadID?=?*((int*)ptr);??
    12. ????nThreadID++;??
    13. ????SetEvent(ghDataEvent);??
    14. ????printf("%d线程启动/n",?nThreadID);??
    15. ????int?i?=?0;??
    16. ????while(!gbExitThread)??
    17. ????{??
    18. ????????Sleep(10000);??
    19. ????}??
    20. ??
    21. ????return?0;??
    22. }??
    23. ??
    24. int?_tmain(int?argc,?_TCHAR*?argv[])??
    25. {??
    26. ????int?nThreadCount?=?10000;??
    27. ????HANDLE*?phaThread?=?new?HANDLE[nThreadCount];??
    28. ????int?nErr?=?0;??
    29. ????for(int?i?=?0;?i?<?nThreadCount;?i++)??
    30. ????{??
    31. ????????phaThread[i]?=?(HANDLE)_beginthreadex(NULL,?0,?SubThread,?&i,?0,?NULL);??
    32. ??
    33. ????????if(phaThread[i]?==?0)??
    34. ????????{??
    35. ????????????nErr?=?GetLastError();??
    36. ????????????if(nErr?==?8)??
    37. ????????????{??
    38. ????????????????printf("开启线程失败,存储空间不足!/n");??
    39. ????????????}??
    40. ????????????else??
    41. ????????????{??
    42. ????????????????printf("开启线程失败,错误号%d/n",?nErr);??
    43. ????????????}??
    44. ??
    45. ????????????break;??
    46. ????????}??
    47. ??
    48. ????????WaitForSingleObject(ghDataEvent,?INFINITE);??
    49. ????}??
    50. ??
    51. ????return?0;??
    52. }??

    ?

    ?

    ?

    2.如何突破2000个限制?
    ??? 你也可以通过连接时修改默认栈大小,将其改的比较小,这样就可以多开一些线程。 如将默认栈的大小改成512K,这样理论上最多就可以开4096个线程。
    ??? 即使物理内存再大,一个进程中可以起的线程总要受到2GB这个内存空间的限制。比方说你的机器装了64GB物理内存,但每个进程的内存空间还是4GB,其中用户态可用的还是2GB。

    ??? 如果是同一台机器内的话,能起多少线程也是受内存限制的。每个线程对象都要站用非页面内存,而非页面内存也是有限的,当非页面内存被耗尽时,也就无法创建线程了。?

    ??? 如果物理内存非常大,同一台机器内可以跑的线程数目的限制值会越来越大。??

    ?

    MSDN原文:

    “The number of threads a process can create is limited by the available virtual memory. By default, every thread has one megabyte of stack space. Therefore, you can create at most 2,048 threads.?If you reduce the default stack size, you can create more threads.?However, your application will have better performance if you create one thread per processor and build queues of requests for which the application maintains the context information. A thread would process all requests in a queue before processing requests in the next queue.”

    ?

    可以通过修改CreateThread参数来缩小线程栈StackSize,例如

    ?

    [cpp]?view plaincopy

    1. #include?"stdafx.h"??
    2. #include?<windows.h>??
    3. #include?<process.h>??
    4. #include?<assert.h>??
    5. ??
    6. volatile?bool?gbExitThread?=?false;??
    7. HANDLE?ghDataEvent?=?CreateEvent(NULL,?FALSE,?FALSE,?NULL);??
    8. ??
    9. UINT?WINAPI?SubThread(void*?ptr)??
    10. {??
    11. ????int?nThreadID?=?*((int*)ptr);??
    12. ????nThreadID++;??
    13. ????SetEvent(ghDataEvent);??
    14. ????printf("%d线程启动/n",?nThreadID);??
    15. ????int?i?=?0;??
    16. ????while(!gbExitThread)??
    17. ????{??
    18. ????????printf("%d:?%d/n",?nThreadID,?i++);??
    19. ????????Sleep(10000);??
    20. ????}??
    21. ??
    22. ????printf("%d线程退出/n",?nThreadID);??
    23. ??
    24. ????return?0;??
    25. }??
    26. ??
    27. int?_tmain(int?argc,?_TCHAR*?argv[])??
    28. {??
    29. ????int?nThreadCount?=?10000;??
    30. ????HANDLE*?phaThread?=?new?HANDLE[nThreadCount];??
    31. ????int?nErr?=?0;??
    32. ????for(int?i?=?0;?i?<?nThreadCount;?i++)??
    33. ????{??
    34. ????????phaThread[i]?=?(HANDLE)_beginthreadex(NULL,?512*1024,?SubThread,?&i,?STACK_SIZE_PARAM_IS_A_RESERVATION,?NULL);??
    35. ????????if(phaThread[i]?==?0)??
    36. ????????{??
    37. ????????????nErr?=?GetLastError();??
    38. ????????????if(nErr?==?8)??
    39. ????????????{??
    40. ????????????????printf("开启线程失败,存储空间不足!/n");??
    41. ????????????}??
    42. ????????????else??
    43. ????????????{??
    44. ????????????????printf("开启线程失败,错误号%d/n",?nErr);??
    45. ????????????}??
    46. ??
    47. ????????????break;??
    48. ????????}??
    49. ??
    50. ????????WaitForSingleObject(ghDataEvent,?INFINITE);??
    51. ????}??
    52. ??
    53. ????return?0;??
    54. }??

    ?

    ?

    ?

    ?

    服务器端程序设计

    如果你的服务器端程序设计成:来一个client连接请求则创建一个线程,那么就会存在2000个限制(在硬件内存和CPU个数一定的情况下)。建议如下:

    The "one thread per client" model is well-known not to scale beyond a dozen clients or so. If you're going to be handling more than that many clients simultaneously, you should move to a model where instead of dedicating a thread to a client, you instead allocate an object. (Someday I'll muse on the duality between threads and objects.) Windows provides I/O completion ports and a?thread pool?to help you convert from a thread-based model to a work-item-based model.

    1. Serve many clients with each thread, and use nonblocking I/O and?level-triggeredreadiness notification

    2. Serve many clients with each thread, and use nonblocking I/O and readiness?changenotification

    3. Serve many clients with each server thread, and use asynchronous I/O

    上面几句哈的核心的思想是:使用异步I/O,和一个线程处理多个客户请求!!

    ?

    二、Linux版本

    https://blog.csdn.net/hhhanpan/article/details/78192653

    最近,在做一个关于聊天服务器的项目,其中遇到了一个问题,那就是一个进程可以产生多少个线程呢?

    开始各种想象,会和不同平台,不同系统相关,网上很多大佬说是1024个,也有256个。

    与其无端猜测,不如动手测试一下。在Linux32位平台,进行测试。

    ?

    ?
    1. 1 #include <stdio.h>

    2. 2 #include <unistd.h>

    3. 3 #include <iostream>

    4. 4 #include <stdlib.h>

    5. 5 #include <string.h>

    6. 6 #include <pthread.h>

    7. 7 #include <errno.h>

    8. 8

    9. 9 using namespace std;

    10. 10 //测试一个进程可以启动多少个线程???

    11. 11

    12. 12 void *thread_function(void *arg);

    13. 13

    14. 14 char message[] = "Hello world";

    15. 15

    16. 16 int main()

    17. 17 {

    18. 18 int res;

    19. 19 pthread_t a_thread;

    20. 20 int i = 0;

    21. 21

    22. 22 while( 1 )

    23. 23 {

    24. 24 //创建线程

    25. 25 res = pthread_create(&a_thread, NULL, thread_function, (void *)messa ge);

    26. 26 i++;

    27. 27 if( res != 0)

    28. 28 {

    29. 29 cout<<"线程个数:"<<i<<endl;

    30. 30 perror("Thread creation failed;errno:");

    31. 31 return 0;

    32. 32 }

    33. 33 }

    34. 34 }

    35. 35

    36. 36 void *thread_function(void *arg)

    37. 37 {

    38. 38 printf("thread_function is runing.Argument is %s\n", (char*)arg);

    39. 39 }

    ?

    ?

    ?

    可能看着会有些粗糙,但是多次测试下来,可以产生304左右个线程。

    32位Linux平台下,虚拟内存空间4G,用户空间占3G,内核空间1G,每个线程的栈大小10240,为10M,3072/10=307。除去主线程,下来接近测试数据。

    通过命令? ulimit -s或者ulimit -a?可以查看默认栈大小

    当然你可以通过命令ulimit -s+参数,临时修改线程栈大小

    线程栈修改之后,线程个数增加了。

    cs