linux——pthread_create()到底可以创建多少个线程?

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014470361/article/details/83352437

pthread_create()到底可以创建多少个线程?

今天在查看pthread_create()函数的使用方法时,比较好奇它到底可以创建多少个线程呢?下面就来测试一番,以下是测试过程。

#include <pthread.h>

#include <stdio.h>

#include <string.h>

#include <unistd.h>

void *ThreadFunc()
{
    static int count = 1;
    printf ("Create thread %d\n", count);
    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;
           }
          usleep(2000);
    }
}

编译,运行:

gcc pthread_test.c  -o pthread_test  -lpthread
./pthread_test 

运行结果如下:
在这里插入图片描述
可以看到linux在创建了381后进程后,报错;Resource temporarily unavailable,资源暂时不可用。那为什么会是381个呢?我们可以使用ulimit -a 来查看自己系统默认设置中线程栈的大小,如下:
在这里插入图片描述
可以看到,stack size 是8192K,及8M。max user processer 是7864个。为什么创建了381个就满了呢?下面看下计算过程:
32位linux下的进程用户空间是3G,即3072M, 3072 M/8M=384个。为什么实际只能创建381呢?这个实际原因还没找到,有知道的网友可以留言告知一下。

修改线程默认栈空间大小

(1)以下是linux查看并修改线程默认栈空间大小的一些方法:
a、通过命令 ulimit -s 查看linux的默认栈空间大小,默认情况下 为8192即8M

b、通过命令 ulimit -s 设置大小值 临时改变栈空间大小:ulimit -s 10240, 即修改为10M

c、可以在/etc/rc.local 内 加入 ulimit -s 10240 则可以开机就设置栈空间大小为10M

d、在/etc/security/limits.conf 中也可以改变栈空间大小:
增加设置:
soft stack 10240
重启后,执行ulimit -s 即可看到改为10240 即10M。
(2)那为啥linux要限制用户进程的栈内存大小?
Why does Linux have a default stack size soft limit of 8 MB?
The point is to protect the OS.
Programs that have a legitimate reason to need more stack are rare. On the other hand, programmer mistakes are common, and sometimes said mistakes lead to code that gets stuck in an infinite loop. And if that infinite loop happens to contain a recursive function call, the stack would quickly eat all the available memory. The soft limit on the stack size prevents this: the program will crash but the rest of the OS will be unaffected.

Note that as this is only a soft limit, you can actually modify it from within your program (see setrlimit(2): get/set resource limits) if you really need to.

线程资源的回收

(3)每次用完进程后都自动的回收资源,继续测试结果:

#include <pthread.h>

#include <stdio.h>

#include <string.h>

#include <unistd.h>

void *ThreadFunc()
{
    static int count = 1;
    printf ("Create thread %d\n", count);
    pthread_detach(pthread_self()); //标记为DETACHED状态,完成后释放自己占用的资源。
    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;
           }
          usleep(2000);
    }
}

在这里插入图片描述
可以看到程序一直在无限循环创建线程,只能使用ctrl+c暂停了。也就是说如我们每次用完线程就释放点资源,是可以创建无限个线程的。线程资源的回收主要有两种:
(a)某个线程完成后,自己主动释放掉资源。使用pthread_detach ( pthread_self ( ) )来释放线程所占用的内存资源(线程内核对象和线程堆栈)。这样就可以创建更多的线程,而不会出现资源暂时不可用的错误了。
如果进程中的某个线程执行了pthread_detach(th),则th线程将处于DETACHED状态,这使得th线程在结束运行时自行释放所占用的内存资源。
(b) 某个线程完成后,另一个线程来释放这个线程的资源。在另一个线程B中调用 int pthread_join(pthread_t thread, void **retval)函数,B线程会一直等待A线程完成,当A线程执行完后,B会把A线程的资源回收回去。举个简单的例子,如下;

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
 
void printids(const char *s)
{
    pid_t pid;
    pthread_t tid;
    pid = getpid();
    tid = pthread_self();
    printf("%s pid %u tid %u (0x%x)\n", s, (unsigned int) pid,
            (unsigned int) tid, (unsigned int) tid);
}
 
void *thr_fn(void *arg)
{
    printids("new thread: ");
    return NULL;
}
 
int main(void)
{
    int err;
    pthread_t ntid;
    err = pthread_create(&ntid, NULL, thr_fn, NULL);
    if (err != 0)
        printf("can't create thread: %s\n", strerror(err));
    printids("main thread:");
    pthread_join(ntid,NULL);
    return EXIT_SUCCESS;
}

gcc main.c -o main
./main
运行结果:
main thread: pid 13073 tid 3077572816 (0xb77008d0)
new thread: pid 13073 tid 3077569392 (0xb76ffb70)
main thread会一直等待new thread完成,待其完成后,把new thread资源释放掉。
所以我们在使用线程时,注意使用pthread_detach()或pthread_join ()释放掉使用的线程资源,防止内存栈的泄漏。

猜你喜欢

转载自blog.csdn.net/u014470361/article/details/83352437