【Linux学习】pthread_create主线程与创建的新线程之间退出关系

本文探讨了主线程与子线程之间的关系,包括主线程退出时子线程的行为,以及不同退出方式对子线程的影响。通过具体示例代码展示了在不同情况下子线程的运行状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们在一个线程中经常会创建另外的新线程,如果主线程退出,会不会影响它所创建的新线程呢?下面就来讨论一下。

 

1、  主线程等待新线程先结束退出,主线程后退出。正常执行。

实例代码:

#include "apue.h"
#include <pthread.h>

pthread_t ntid;//线程ID

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 *thrfun(void *arg){
        //sleep(1);//使得主线程先退出
        printids("new thread");

        return ((void *)0);
}

int main(){
        int err;
        err = pthread_create(&ntid,NULL,thrfun,NULL);

        if(err != 0)
                err_quit("can't create thread: %s\n",strerror(err));
        printids("main thread");

        sleep(1);//等待新线程先结束

        exit(0);
}
运行结果:


2、  进程先退出,新线程也会立即退出,系统清除所有资源。

实例代码:

#include "apue.h"
#include <pthread.h>

pthread_t ntid;//线程ID

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 *thrfun(void *arg){
        sleep(1);//使得主线程先退出
        printids("new thread");

        return ((void *)0);
}

int main(){
        int err;
        err = pthread_create(&ntid,NULL,thrfun,NULL);

        if(err != 0)
                err_quit("can't create thread: %s\n",strerror(err));
        printids("main thread");

        //sleep(1);

        exit(0);//注意是进程(不是线程)退出
}

运行结果:


可以发现主线程退出后所创建的新线程也停止运行了。


3、如果主线程调用了pthread_exit,那么它退出了,子线程也不会退出。

实例代码:

#include "apue.h"
#include <pthread.h>

pthread_t ntid;//线程ID

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 *thrfun(void *arg){
        sleep(1);//使得主线程先退出
        printids("new thread");

        return ((void *)0);
}

int main(){
        int err;
        err = pthread_create(&ntid,NULL,thrfun,NULL);

        if(err != 0)
                err_quit("can't create thread: %s\n",strerror(err));
        printids("main thread");

        //sleep(1);

            pthread_exit(NULL);

        exit(0);
}
运行结果:



POSIX标准定义:

When you program with POSIX Threads API,there is one thing about pthread_exit() that you may ignore for mistake. Insubroutines that complete normally, there is nothing special you have to dounless you want to pass a return code back using pthread_exit(). The completionwon't affect the other threads which were created by the main thread of thissubroutine. However, in main(), when the code has been executed to the end,there could leave a choice for you. If you want to kill all the threads thatmain() created before, you can dispense with calling any functions. But if you want to keep the process and all the other threadsexcept for the main thread alive after the exit of main(), then you can call pthread_exit()to realize it. And any files opened inside the main thread will remain openafter its termination.

 

按照POSIX标准定义,当主线程在子线程终止之前调用pthread_exit()时,子线程是不会退出的。

 

注意:这里在main函数中调用pthread_exit()只会是主线程退出,而进程并未退出。因此新线程继续执行而没有退出。

我们可以在return 0;这条语句前面添加一条输出语句printf(“Mainthread has exited!\n”);来进行测试,输出结果不发生任何变化,说明这条语句没有被执行到。也就说明进程并未退出。

 

因此:

一个线程的退出不会影响另外一个线程。但是进程结束,所有线程也就结束了,所有资源会被回收。

 

我们可以再写一个程序来进行验证:

4、在创建的新线程B中再次创建新线程C,那么如果B先退出,那么C将会继续执行而不会退出。

实例代码:

#include "apue.h"
#include<pthread.h>

pthread_t ntid;//线程ID

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 *thrfun2(void *arg){
        sleep(1);//使得创建它的主线程先退出
        printids("new thread of the new thread");

        return ((void *)0);
}

void *thrfun(void *arg){
        sleep(1);//使得主线程先退出
        printids("new thread");
        int err;
        err = pthread_create(&ntid,NULL,thrfun2,NULL);

        if(err != 0)
                err_quit("can'tcreate thread: %s\n",strerror(err));

        return ((void *)0);
}

int main(){
        int err;
        err = pthread_create(&ntid,NULL,thrfun,NULL);

        if(err != 0)
                err_quit("can'tcreate thread: %s\n",strerror(err));
        printids("main thread");

        //sleep(1);

        pthread_exit(NULL);

        printf("main thread has exited!\n");

        exit(0);
}

运行结果:






Linux环境下,`pthread_create()` 是用于创建新线程的函数,它是POSIX线程库 (pthread) 提供的一个核心接口。这个函数让你能够在主进程中启动一个新的执行流,即线程。 `pthread_create()` 的基本原型如下: ```c #include <pthread.h> int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg); ``` 参数说明如下: - `pthread_t *thread`: 指针,用于存储新线程的标识符。调用结束后,该指针指向新线程。 - `const pthread_attr_t *attr`: 可选参数,线程属性结构体,可以设置线程的一些特性,如优先级、栈大小等,默认值通常是 NULL。 - `void *(*start_routine)(void*)`: 函数指针,指向要在线程执行的入口点,通常称为 "thread function" 或 "thread start routine"。 - `void *arg`: 可选参数,传递给 "start_routine" 函数的第一个参数(如果有的话)。 创建线程的基本步骤如下: 1. 包含必要的头文件 `#include <pthread.h>`。 2. 定义要在线程中运行的函数,该函数应该接受一个 `void *` 类型的参数(即使需要实际使用它)。 3. 使用 `pthread_create()` 函数创建线程,同时传入新线程的标识符、可能的属性以及线程函数和参数。 例如: ```c #include <pthread.h> #include <stdio.h> void *my_thread_function(void *data) { printf("Hello from thread %p\n", data); return NULL; } int main() { pthread_t new_thread; // 创建线程 if (pthread_create(&new_thread, NULL, my_thread_function, (void *)"Thread 1")) { perror("Error creating thread"); exit(1); } // 等待线程结束 pthread_join(new_thread, NULL); printf("Main thread exiting.\n"); return 0; } ``` 在这个例子中,`main` 函数创建了一个新的线程,该线程会打印一条消息并退出主线程随后等待新线程完成。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

没有昵称阿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值