111.连接已终止的线程、线程分离、线程取消

本文详细介绍了在C语言中如何与已终止的线程连接,回收子线程资源,以及使用pthread_detach和pthread_cancel进行线程分离和取消操作。通过实例展示了这些线程管理函数的用法和注意事项。
摘要由CSDN通过智能技术生成

一、连接已终止的线程

功能:和一个已经终止的线程进行连接

           回收子线程的资源

           这个函数是阻塞函数,调用一次只能回收一个子线程

参数:thread:需要回收的子线程的ID

           retval: 接收子线程推出时的返回值

返回值:0 成功

              非0  失败,返回错误号

代码示例:

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

void *callback(void *arg)
{
    printf("child pthread id:%ld\n", (long)pthread_self());
    sleep(3);
    return NULL;
}

int main()
{
    pthread_t tid;

    int ret = pthread_create(&tid, NULL, callback, NULL);

    if (ret != 0)
    {
        char *errstr = strerror(ret);
        printf("error: %s\n", errstr);
        return 1;
    }

    // 主线程
    for (int i = 0; i < 5; i++)
    {
        printf("%d\n", i);
    }

    printf("tid:%ld, main thread id:%ld\n", (long)tid, (long)pthread_self());

    //主线程调用pthread_join回收子线程的资源
    ret=pthread_join(tid, NULL);

    if (ret != 0)
    {
        char *errstr = strerror(ret);
        printf("error: %s\n", errstr);
        return 1;
    }

    printf("回收子线程资源成功!\n");

    // 等待子线程结束
    pthread_exit(NULL);

    return 0;
}

这里将在child id打印之后,睡眠3s才会打印回收子线程资源成功

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

//int value=10;//全局变量
void *callback(void *arg)
{
    printf("child pthread id:%ld\n", (long)pthread_self());
    // sleep(3);
    // return NULL;
    int value = 10;//局部变量
    pthread_exit((void *)&value);
}

int main()
{
    pthread_t tid;

    int ret = pthread_create(&tid, NULL, callback, NULL);

    if (ret != 0)
    {
        char *errstr = strerror(ret);
        printf("error: %s\n", errstr);
        return 1;
    }

    // 主线程
    for (int i = 0; i < 5; i++)
    {
        printf("%d\n", i);
    }

    printf("tid:%ld, main thread id:%ld\n", (long)tid, (long)pthread_self());

    // 主线程调用pthread_join回收子线程的资源
    int *pthread_retval;
    ret = pthread_join(tid, (void **)&pthread_retval);

    if (ret != 0)
    {
        char *errstr = strerror(ret);
        printf("error: %s\n", errstr);
        return 1;
    }

    printf("xeti data:%d\n", *pthread_retval);

    printf("回收子线程资源成功!\n");

    // 等待子线程结束
    pthread_exit(NULL);

    return 0;
}

二、线程分离

pthread_detach 是 POSIX 线程库中的一个函数,用于将线程标记为“分离状态”,以表明当线程退出时,其资源可以被系统自动回收,而不需要等待其他线程调用 pthread_join 来获取线程的退出状态。

以下是 pthread_detach 的基本语法:

#include <pthread.h>

int pthread_detach(pthread_t thread);
  • thread:要标记为分离状态的线程的线程标识符。

调用 pthread_detach 函数后,指定的线程就会变成“分离状态”的线程。这意味着当该线程退出时,它的资源(包括线程控制块等)会被自动回收,而不会形成僵尸线程。分离状态的线程不再需要其他线程调用 pthread_join 来进行清理。

代码示例:

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

void *callback(void *arg)
{
    printf("child pthread id:%ld\n", (long)pthread_self());
    return NULL;
}

int main()
{
    pthread_t tid;

    int ret = pthread_create(&tid, NULL, callback, NULL);

    if (ret != 0)
    {
        char *errstr = strerror(ret);
        printf("error1: %s\n", errstr);
        return 1;
    }

    printf("tid:%ld, main thread id:%ld\n", tid, pthread_self());

    // 设置子线程分离,子线程分离后,子线程结束时对应的资源就不需要主线程释放
    ret = pthread_detach(tid);

    if (ret != 0)
    {
        char *errstr = strerror(ret);
        printf("error2: %s\n", errstr);
        return 1;
    }

    ret = pthread_join(tid, NULL);

    if (ret != 0)
    {
        char *errstr = strerror(ret);
        printf("error3: %s\n", errstr);
        return 1;
    }

    // 等待子线程结束
    pthread_exit(NULL);

    return 0;
}

此时已经子线程分离了,在调用pthread_join就会报错

 三、线程取消

pthread_cancel 是 POSIX 线程库中的一个函数,用于请求取消另一个线程的执行。这个函数的使用需要非常小心,因为线程可能正在执行一些关键的任务,而取消可能引起资源泄漏或不一致性的问题。

以下是 pthread_cancel 的基本语法:

#include <pthread.h>

int pthread_cancel(pthread_t thread);
  • thread:要取消的线程的线程标识符。

调用 pthread_cancel 函数将发送一个取消请求给指定的线程。实际上,它并不会立即终止线程的执行,而是等待线程到达取消点(cancellation point)。取消点是一些由线程库定义的特定位置,线程在这些位置上检查是否有取消请求。如果线程在取消点上,它会执行相应的取消动作。如果线程没有到达取消点,取消请求会在线程到达下一个取消点时生效。

要使一个线程支持取消请求,可以使用以下两个函数:

pthread_setcancelstate:

#include <pthread.h>

int pthread_setcancelstate(int state, int *oldstate);
  • state:用于设置取消状态的值,可以是 PTHREAD_CANCEL_ENABLE(启用取消)或 PTHREAD_CANCEL_DISABLE(禁用取消)。
  • oldstate:用于存储原始取消状态的变量的地址。如果不关心原始状态,可以将其设置为 NULL

pthread_setcanceltype:

#include <pthread.h>

int pthread_setcanceltype(int type, int *oldtype);
  • type:用于设置取消类型的值,可以是 PTHREAD_CANCEL_DEFERRED(延迟取消)或 PTHREAD_CANCEL_ASYNCHRONOUS(异步取消)。
  • oldtype:用于存储原始取消类型的变量的地址。如果不关心原始类型,可以将其设置为 NULL

代码示例:

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

void *thread_function(void *arg) {
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);

    while (1) {
        printf("线程正在执行\n");
        sleep(1);
    }

    pthread_exit(NULL);
}

int main() {
    pthread_t thread_id;

    // 创建一个线程
    pthread_create(&thread_id, NULL, thread_function, NULL);

    // 等待一段时间
    sleep(3);

    // 发送取消请求
    pthread_cancel(thread_id);

    // 等待线程结束
    pthread_join(thread_id, NULL);

    printf("主线程结束\n");

    return 0;
}

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

清酒。233

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

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

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

打赏作者

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

抵扣说明:

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

余额充值