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

一、连接已终止的线程

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

回收子线程的资源

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

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

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

返回值:0 成功

非0 失败,返回错误号

代码示例:

cpp 复制代码
#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才会打印回收子线程资源成功

cpp 复制代码
#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 的基本语法:

cpp 复制代码
#include <pthread.h>

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

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

代码示例:

cpp 复制代码
#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 的基本语法:

cpp 复制代码
#include <pthread.h>

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

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

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

pthread_setcancelstate:

cpp 复制代码
#include <pthread.h>

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

pthread_setcanceltype:

cpp 复制代码
#include <pthread.h>

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

代码示例:

cpp 复制代码
#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;
}
相关推荐
天下皆白_唯我独黑5 分钟前
php 使用qrcode制作二维码图片
开发语言·php
夜雨翦春韭9 分钟前
Java中的动态代理
java·开发语言·aop·动态代理
小远yyds11 分钟前
前端Web用户 token 持久化
开发语言·前端·javascript·vue.js
何曾参静谧23 分钟前
「C/C++」C/C++ 之 变量作用域详解
c语言·开发语言·c++
q567315231 小时前
在 Bash 中获取 Python 模块变量列
开发语言·python·bash
许野平1 小时前
Rust: 利用 chrono 库实现日期和字符串互相转换
开发语言·后端·rust·字符串·转换·日期·chrono
也无晴也无风雨1 小时前
在JS中, 0 == [0] 吗
开发语言·javascript
狂奔solar1 小时前
yelp数据集上识别潜在的热门商家
开发语言·python
blammmp2 小时前
Java:数据结构-枚举
java·开发语言·数据结构
何曾参静谧2 小时前
「C/C++」C/C++ 指针篇 之 指针运算
c语言·开发语言·c++