线程相关函数(1)-pthread_create(), pthread_join(), pthread_exit(), pthread_cancel() 创建取消线程

本文深入解析线程管理核心函数:pthread_create(), pthread_join(), pthread_exit(), pthread_cancel()。详细介绍各函数参数、返回值及注意事项,并提供示例代码,展示如何创建、回收、退出和取消线程。

线程相关函数(1)-pthread_create(), pthread_join(), pthread_exit(), pthread_cancel() 创建取消线程

阅读目录

回到顶部

一. pthread_create()

#include <pthread.h>

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
 

pthread_t *thread:           传递一个pthread_t变量地址进来,用于保存新线程的tid(线程ID)
const pthread_attr_t *attr:      线程属性设置,如使用默认属性,则传NULL
void *(*start_routine) (void *):      函数指针,指向新线程应该加载执行的函数模块
void *arg:            指定线程将要加载调用的那个函数的参数

返回值:成功返回0,失败返回错误号。以前学过的系统函数都是成功返回0,失败返回-1,而错误号保存在全局变量errno中,而pthread库的函数都是通过返回值返回错误号,虽然每个线程也都有一个errno,但这是为了兼容其它函数接口而提供的,pthread库本身并不使用它,通过返回值返回错误码更加清晰。

 

回到顶部

二.pthread_join()

#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);


pthread_t thread:        回收线程的tid
void **retval:          接收退出线程传递出的返回值
返回值:成功返回0,失败返回错误号

注意:

调用该函数的线程将挂起等待,直到id为thread的线程终止。thread线程以不同的方法终止,通过pthread_join得到的终止状态是不同的,总结如下:

如果thread线程通过return返回,retval所指向的单元里存放的是thread线程函数的返回值。
如果thread线程被别的线程调用pthread_cancel异常终止掉,retval所指向的单元里存放的是常数PTHREAD_CANCELED。
如果thread线程是自己调用pthread_exit终止的,retval所指向的单元存放的是传给pthread_exit的参数。

如果对thread线程的终止状态不感兴趣,可以传NULL给retval参数。

回到顶部

三.pthread_exit()

#include <pthread.h>
void pthread_exit(void *retval);
void *retval:      线程退出时传递出的参数,可以是退出值或地址,如是地址时,不能是线程内部申请的局部地址。

注意和exit函数的区别,任何线程里exit导致进程退出,其他线程未工作结束,主线程退出时不能return或exit。需要注意,pthread_exit或者return返回的指针所指向的内存单元必须是全局的或者是用malloc分配的,不能在线程函数的栈上分配,因为当其它线程得到这个返回指针时线程函数已经退出了。
 

回到顶部

四.pthread_cancel()

#include <pthread.h>
int pthread_cancel(pthread_t thread);

定义在Linux的pthread库中常数PTHREAD_CANCELED的值是-1。可以在头文件pthread.h中找到它的定义:

#define PTHREAD_CANCELED ((void *) -1)

回到顶部

五.示例

复制代码

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>


void *thr_fn1(void *arg)
{
    printf("thread 1 returning\n");
    return (void*)1;
}


void *thr_fn2(void *arg)
{
    printf("thread 2 exiting\n");
    pthread_exit((void*)2);
}


void *thr_fn3(void *arg)
{
    while(1) {
        printf("thread 3 writing\n");
        sleep(1);
    }
}


int main()
{
    pthread_t tid;
    void *retval;

    pthread_create(&tid, NULL, thr_fn1, NULL);
    pthread_join(tid, &retval);
    printf("thread 1 exit code %d\n", (int)retval);    
    
    pthread_create(&tid, NULL, thr_fn2, NULL);
    pthread_join(tid, &retval);
    printf("thread 2 exit code %d\n", (int)retval);

    pthread_create(&tid, NULL, thr_fn3, NULL);
    sleep(3);
    // 调用pthread_cancel函数取消第三个线程
    pthread_cancel(tid);
    // 如果线程是通过pthread_cancel异常终止掉,retval所指向的单元里存放的是常数PTHREAD_CANCELED
    pthread_join(tid, &retval);
    printf("thread 3 exit code %d\n", (int)retval);
    
    return 0;
}

复制代码

运行结果:

thread 1 returning
thread 1 exit code 1
thread 2 exiting
thread 2 exit code 2
thread 3 writing
thread 3 writing
thread 3 writing
thread 3 exit code -1

<think> 我们被要求回答关于pthread_createpthread_joinpthread_exitpthread_detach的使用方法和区别。根据提供的引用,我们可以总结如下: 1. pthread_create:用于创建线程。 2. pthread_join:用于等待指定线程结束并回收其资源(阻塞调用者)。 3. pthread_exit:用于终止当前线程,并可返回一个值。 4. pthread_detach:分离线程,使得线程结束后自动释放资源,无需其他线程调用pthread_join。 注意:一个线程不能被同时连接(join)和分离(detach),一旦分离就不能再连接(引用[3])。另外,分离线程可以在创建时设置属性,也可以在创建后调用pthread_detach。 我们将按照以下结构回答: - 分别介绍每个函数的功能、参数和返回值。 - 说明它们之间的区别和联系。 - 给出使用示例(根据引用中的代码示例)。 - 注意事项(如不能对已分离的线程调用pthread_join)。 同时,我们会生成相关问题。 </think> ### pthread_createpthread_joinpthread_exitpthread_detach详解 #### 1. pthread_create线程创建 **功能**:创建线程 **原型**: ```c int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg); ``` **参数说明**: - `thread`:输出参数,存储新线程ID - `attr`:线程属性(NULL表示默认属性) - `start_routine`:线程入口函数 - `arg`:传递给入口函数的参数 **返回值**:成功返回0,失败返回错误码 **示例**: ```c pthread_t tid; void* thread_func(void* arg) { /* 线程逻辑 */ } pthread_create(&tid, NULL, thread_func, NULL); ``` #### 2. pthread_join线程资源回收 **功能**:阻塞等待指定线程结束并回收资源[^2] **原型**: ```c int pthread_join(pthread_t thread, void **retval); ``` **参数说明**: - `thread`:目标线程ID - `retval`:接收线程退出状态(可为NULL) **注意事项**: - 只能对 *joinable*(非分离)线程调用 -join线程会残留资源(类似僵尸进程) - 线程结束前会阻塞调用者[^2] #### 3. pthread_exit线程主动退出 **功能**:终止当前线程并返回状态值[^4] **原型**: ```c void pthread_exit(void *retval); ``` **参数说明**: - `retval`:线程退出状态(可由pthread_join捕获) **特点**: - 不同于`return`,可在任意函数深度退出线程 -线程调用时不会终止进程(仅退出自身) **示例**: ```c void* worker(void* arg) { if(error) pthread_exit((void*)-1); return (void*)0; // 正常退出 } ``` #### 4. pthread_detach:线程分离 **功能**:设置线程为分离状态,结束后自动回收资源[^3] **原型**: ```c int pthread_detach(pthread_t thread); ``` **特点**: - 分离后无需也不能调用`pthread_join`[^3] - 可在线程内调用`pthread_detach(pthread_self())` - 资源回收由系统自动完成 **典型用法**: ```c pthread_create(&tid, NULL, func, NULL); pthread_detach(tid); // 主线程不阻塞等待 ``` --- ### 关键区别总结 | 函数 | 作用 | 资源回收方式 | 阻塞调用者 | |-----------------|-----------------------|----------------------|------------| | `pthread_join` | 等待线程结束 | 手动回收(需显式调用) | 是 | | `pthread_detach`| 设置线程分离 | 系统自动回收 | 否 | | `pthread_exit` | 终止当前线程 | 依赖join/detach设置 | - | | `pthread_create`| 创建线程 | - | - | > ⚠️ **重要规则**: > 1. 线程**不能同时被join和detach**[^3] > 2. 未分离且未join线程会造成资源泄漏 > 3. 主线程退出会导致所有线程终止(除非调用`pthread_exit`) --- ### 综合示例 ```c #include <pthread.h> void* worker(void* arg) { printf("Working...\n"); pthread_exit(NULL); // 显式退出 } int main() { pthread_t tid; pthread_create(&tid, NULL, worker, NULL); // 可选方案1:等待回收 pthread_join(tid, NULL); // 可选方案2:分离(二选一) // pthread_detach(tid); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值