線程應用程序最常見導致創建線程失敗的原因是線程棧大小的設置。創建一個新的線程,默認情況下系統為線程棧預留了2MB的尋址空間。線程棧起始于進程虛擬 內存的高端地址,并向虛擬內存底端地址方向擴展。取決于線程本身的大小以及其它線程內存分配的情況,進程虛擬地址空間消耗過快可能導致創建線程失敗。
這里有一個測試程序可以看到,Linux下最多可以創建多少個線程。
#include <pthread.h>
#include <stdio.h>
#include <string.h>
?
void *ThreadFunc()
{
????static int count = 1;
????printf ("Create thread%d/n", count);
????pthread_detach(pthread_self());
????count++;
???
}
?
main(void)
{
????int?????err;
????pthread_t tid;
????while (1){
???????????err= pthread_create(&tid, NULL, ThreadFunc, NULL);
???????????if(err != 0){
???????????????printf("can't create thread: %s/n",strerror(err));
???????????break;
???????????}??
????}
}
輸出結果如下:
Create thread 301
Create thread 302
can't create thread: Cannot allocate memory
用?ulimit -s?可以查看到棧的默認大小為10240K
32位linux下的進程用戶空間是3072M,?3072/10.24=300。為什么實際會比計算出來的多2個,這個原因還不太清楚。(編者注:準確算法是(3072*1024K)/10240K=307.2,實際會比計算出來的少5.2個)
可以在調用pthread_create?的時候用?pthread_attr_getstacksize?設置棧的大小,或者直接用?ulimit -s?設置棧的大小。
如果修改上面的測試代碼為
#include <pthread.h>
#include <stdio.h>
#include <string.h>
?
void *ThreadFunc()
{
????static int count = 1;
????printf ("Create thread%d/n", count);
????pthread_detach(pthread_self());
????count++;
???
}
?
main(void)
{
????int?????err;
????pthread_t tid;
????while (1){
???????????err= pthread_create(&tid, NULL, ThreadFunc, NULL);
???????????if(err != 0){
???????????????printf("can'tcreate thread: %s/n", strerror(err));
???????????break;
???????????}??
????}
}
那么得到的結果將是:
Create thread 560000
Create thread 560001
……………
這里用到了pthread_detach(pthread_self())來釋放線程所占用的內存資源(線程內核對象和線程堆棧)。這樣就可以創建更多的線程,而不會出現Cannot allocate memory的錯誤。
如果進程中的某個線程執行了pthread_detach(th),則th線程將處于DETACHED狀態,這使得th線程在結束運行時自行釋放所占用的內存資源。一個可join的線程所占用的內存僅當有線程對其執行了pthread_join()后才會釋放,因此為了避免內存泄漏,所有線程的終止,要么已設為DETACHED,要么就需要使用pthread_join()來回收