而一個進程中可用的內(nèi)存空間只有2G,所以理論上一個進程中最多可以開2048個線程
但是內(nèi)存當然不可能完全拿來作線程的棧,所以實際數(shù)目要比這個值要小。
你也可以通過連接時修改默認棧大小,將其改的比較小,這樣就可以多開一些線程。
如將默認棧的大小改成512K,這樣理論上最多就可以開4096個線程。
即使物理內(nèi)存再大,一個進程中可以起的線程總要受到2GB這個內(nèi)存空間的限制。
比方說你的機器裝了64GB物理內(nèi)存,但每個進程的內(nèi)存空間還是4GB,其中用戶態(tài)可用的還是2GB。
如果是同一臺機器內(nèi)的話,能起多少線程也是受內(nèi)存限制的。每個線程對象都要站用非頁面內(nèi)存,而非頁面內(nèi)存也是有限的,當非頁面內(nèi)存被耗盡時,也就無法創(chuàng)建線程了。
如果物理內(nèi)存非常大,同一臺機器內(nèi)可以跑的線程數(shù)目的限制值會越來越大。
在Windows下寫個程序,一個進程Fork出2000個左右線程就會異常退出了,為什么?
這個問題的產(chǎn)生是因為windows32位系統(tǒng),一個進程所能使用的最大虛擬內(nèi)存為2G,而一個線程的默認線程棧StackSize為1024K(1M),這樣當線程數(shù)量逼近2000時,2000*1024K=2G(大約),內(nèi)存資源就相當于耗盡。
MSDN原文:
“The number of threads a process can create is limited by theavailable virtual memory. By default, every thread has one megabyte ofstack space. Therefore, you can create at most 2,028 threads. If youreduce the default stack size, you can create more threads. However,your application will have better performance if you create one threadper processor and build queues of requests for which the applicationmaintains the context information. A thread would process all requestsin a queue before processing requests in the next queue.”
如何突破2000個限制?
可以通過修改CreateThread參數(shù)來縮小線程棧StackSize,例如
#define MAX_THREADS 50000
DWORD WINAPI ThreadProc( LPVOID lpParam ){
while(1){
Sleep(100000);
}
return 0;
}
int main() {
DWORD dwThreadId[MAX_THREADS];
HANDLE hThread[MAX_THREADS];
for(int i = 0; i < MAX_THREADS; ++i)
{
hThread[i] = CreateThread(0, 64, ThreadProc, 0, STACK_SIZE_PARAM_IS_A_RESERVATION, &dwThreadId[i]);
if(0 == hThread[i])
{
DWORD e = GetLastError();
printf("%d\r\n",e);
break;
}
}
ThreadProc(0);
}
服務器端程序設計
如果你的服務器端程序設計成:來一個client連接請求則創(chuàng)建一個線程,那么就會存在2000個限制(在硬件內(nèi)存和CPU個數(shù)一定的情況下)。建議如下:
The "one thread per client" model is well-known not to scale beyonda dozen clients or so. If you're going to be handling more than thatmany clients simultaneously, you should move to a model where instead ofdedicating a thread to a client, you instead allocate an object.(Someday I'll muse on the duality between threads and objects.) Windowsprovides I/O completion ports and a thread pool to help you convert froma thread-based model to a work-item-based model.
1. Serve many clients with each thread, and use nonblocking I/O and level-triggered readiness notification
2. Serve many clients with each thread, and use nonblocking I/O and readiness change notification
3. Serve many clients with each server thread, and use asynchronous I/O
--------------------
附:Win32將低區(qū)的2GB留給進程使用, 高區(qū)的2GB則留給系統(tǒng)使用。
Linux將高位1GB留給內(nèi)核,低位3GB留給進程。