Linux C pthread多线程,join和detach

Linux C使用pthread进行多线程编程时,有一个注意点:新启动的子线程一定要在主线程或启动它的父线程中join,或者本身被设置为detach,否则会引起资源泄露,资源比如每个线程都有自己的运行stack,内核中的task_stuct数据结够等。有点儿类似父子进程中的子进程退出没有被父进程join就会变成僵尸进程一样。

文章后面的例子最终会导致资源耗尽 pthread_create 返回 11这个错误码. 它对应的宏是EAGAIN,意思就是操作系统没有资源创建新的线程了。

根据 https://pubs.opengroup.org/onlinepubs/7908799/xsh/pthread_create.html 说明:

[EAGAIN]
The system lacked the necessary resources to create another thread, or the system-imposed limit on the total number of threads in a process PTHREAD_THREADS_MAX would be exceeded.
[EINVAL]

在系统的搜索路径 /usr/include, /usr/local/include 中搜索这个宏定义:

root@ubuntu:/media/sf_VMshare/test# grep EAGAIN /usr/include/ -rn|grep define
/usr/include/asm-generic/errno.h:22:#define	EWOULDBLOCK	EAGAIN	/* Operation would block */
/usr/include/asm-generic/errno-base.h:15:#define	EAGAIN		11	/* Try again */

导致pthread_create返回11的例子:

#include 
#include 
#include 
#include 

int g_count = 0;

void *thread_count(void *arg)
{
    g_count++;
    return NULL;
}

void *thread_show(void *arg)
{
    while (1) {
        printf("g_count: %d\n", g_count);
        sleep(1);
    }
    return NULL;
}


int main(int argc, char *argv[])
{
#define CHECK_RET(fun, ret) if (ret != 0) {strcpy(fun_name, #fun); goto done;}
    char fun_name[256] = {0};
    int ret;
    pthread_t tid;

    ret =  pthread_create(&tid, NULL, thread_show,  NULL);
    CHECK_RET(pthread_create, ret);
    while(1) {
        ret = pthread_create(&tid, NULL, thread_count, NULL);
        CHECK_RET(pthread_create, ret);
    }

done:
    printf("%s ret: %d, g_count: %d\n", fun_name, ret, g_count);
    return -1;
#undef CHECK_RET
}
/*
root@ubuntu:/media/sf_VMshare/test# ./a.out
g_count: 212
g_count: 30110
pthread_create ret: 11, g_count: 32682
*/

这个问题解决可用用下面三个办法解决:

  1. 在子线程中设置 pthread_detach(pthread_self()), 注意保证主线程在子线程运行结束前不会运行结束或退出;
  2. 在主线程中对对应的子线程调用 pthread_join, 注意这个是一个阻塞调用,阻塞到子线程运行结束;
  3. 在主线程启动子线程时就设置好属性 pthread_attr_t : PTHREAD_CREATE_DETACHED,注意点同1;

通过上面三个办法,都不会再有pthread_create返回11的错误了,join或detach可以让OS及时回收对应资源。

你可能感兴趣的:(C/C++,OS/Linux)