【Linux系统编程】31.pthread_detach、线程属性

目录

pthread_detach

参数pthread

返回值

测试代码1

测试结果

pthread_attr_init

参数attr

返回值

pthread_attr_destroy

参数attr

返回值

pthread_attr_setdetachstate

参数attr

参数detachstate

返回值

测试代码2

测试结果

线程使用注意事项

pthread_detach

       实现线程分离。线程分离状态:指定该状态,线程主动与主控线程断开关系。线程结束后,其退出状态不由其他线程获取,而直接自己自动释放。网络、多线程服务器常用。

man 3 pthread_detach

参数pthread

待分离的线程ID。

返回值

成功:0

失败:错误号

测试代码1

分离一个线程,并回收。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <string.h>

void *HuiDiao_HanShu(void *arg)
{
    printf("这是子线程的回调函数,子线程的进程ID是%d,子线程ID是%lu。\n", getpid(), pthread_self());
    return (void *)0;
}

int main(int argc, char *argv[])
{
    int flag;
    pthread_t ZiXianCheng_ID; //子线程ID
    void *num = NULL;

    flag = pthread_create(&ZiXianCheng_ID, NULL, HuiDiao_HanShu, NULL); //创建子线程
    if (flag != 0)
    {
        printf("创建子线程错误:%s\n", strerror(flag));
        exit(1);
    }

    printf("这是主线程,进程ID是%d,线程ID是%lu。\n", getpid(), pthread_self());

    printf("开始分离子线程!\n");
    flag = pthread_detach(ZiXianCheng_ID);
    if (flag != 0)
    {
        printf("分离子线程错误:%s\n", strerror(flag));
        exit(1);
    }
    printf("分离子线程完成!\n");

    printf("这是主线程,先睡一会,再回收子线程!\n");
    sleep(1);
    printf("这是主线程,睡醒了!\n");

    printf("开始回收子线程!\n");
    flag = pthread_join(ZiXianCheng_ID, &num);
    if (flag != 0)
    {
        printf("回收子线程错误:%s\n", strerror(flag));
        exit(1);
    }
    printf("回收子线程完成!\n");
    printf("num=%d\n", (int)num);

    pthread_exit(NULL);

    return 0;
}

测试结果

分离后的子线程结束后,会自动清理PCB,无需回收。

pthread_attr_init

初始化线程属性。

man 3 pthread_attr_init

参数attr

传出参数的属性。

返回值

成功:0

失败:错误号

pthread_attr_destroy

销毁线程属性所占用的资源。

man 3 pthread_attr_destroy

参数attr

传出参数的属性。

返回值

成功:0

失败:错误号

pthread_attr_setdetachstate

设置线程属性。

man 3 pthread_attr_setdetachstate

参数attr

已初始化的线程属性。

参数detachstate

分离线程:PTHREAD_CREATE_DETACHED

非分离线程:PTHREAD _CREATE_JOINABLE

返回值

成功:0

失败:错误号

测试代码2

设置线程的属性为分离属性,再回收子进程。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <string.h>

void *HuiDiao_HanShu(void *arg)
{
    printf("这是子线程的回调函数,子线程的进程ID是%d,子线程ID是%lu。\n", getpid(), pthread_self());
    return (void *)0;
}

int main(int argc, char *argv[])
{
    int flag;
    pthread_t ZiXianCheng_ID;         //子线程ID
    pthread_attr_t XianCheng_ShuXing; //线程属性
    void *num = NULL;

    flag = pthread_attr_init(&XianCheng_ShuXing); //初始化线程属性
    if (flag != 0)
    {
        printf("线程属性初始化错误:%s\n", strerror(flag));
        exit(1);
    }

    flag = pthread_attr_setdetachstate(&XianCheng_ShuXing, PTHREAD_CREATE_DETACHED); //设置线程属性为分离属性
    if (flag != 0)
    {
        printf("设置线程属性错误:%s\n", strerror(flag));
        exit(1);
    }

    flag = pthread_create(&ZiXianCheng_ID, &XianCheng_ShuXing, HuiDiao_HanShu, NULL); //创建子线程,借助线程属性将子进程分离
    if (flag != 0)
    {
        printf("创建子线程错误:%s\n", strerror(flag));
        exit(1);
    }

    flag = pthread_attr_destroy(&XianCheng_ShuXing); //销毁线程属性
    if (flag != 0)
    {
        printf("线程属性销毁错误:%s\n", strerror(flag));
        exit(1);
    }

    printf("这是主线程,进程ID是%d,线程ID是%lu。\n", getpid(), pthread_self());

    printf("这是主线程,先睡一会,再回收子线程!\n");
    sleep(1);
    printf("这是主线程,睡醒了!\n");

    printf("开始回收子线程!\n");
    flag = pthread_join(ZiXianCheng_ID, &num);
    if (flag != 0)
    {
        printf("回收子线程错误:%s\n", strerror(flag));
        exit(1);
    }
    printf("回收子线程完成!\n");
    printf("num=%d\n", (int)num);

    pthread_exit(NULL);

    return 0;
}

测试结果

说明子线程已被成功分离,无需回收。

线程使用注意事项

  1. 主线程退出其他线程不退出,主线程应调用 pthread_exit。

  2. 避免僵尸线程,被join线程可能在join函数返回前就释放完自己的所有内存资源,所以不应当返回被回收线程栈中的值。

  3. malloc和mmap申请的内存可以被其他线程释放。

  4. 应避免在多线程模型中调用fork除非马上exec,子进程中只有调用fork的线程存在,其他线程在子进程中均 pthread_exit。

  5. 信号的复杂语义很难和多线程共存,应避免在多线程引入信号机制。

  • 21
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
通过pthread_create和pthread_exit调用参数与线程T2交换数据的方法如下: 1. 首先,在主线程中创建线程T2和线程T1,通过pthread_create函数传递参数给线程T2。例如,可以通过定义一个结构体来传递需要交换的数据,然后将该结构体指针作为参数传递给pthread_create函数。 2. 在线程T2中,通过解引用参数指针来获取到传递的数据。可以使用类型转换将void类型的参数指针转换为所需的类型,然后再进行解引用操作。 3. 在线程T2中,通过修改数据来与线程T1交换数据。可以通过指针操作来修改数据内容。 4. 线程T2执行完毕后,可以通过pthread_exit函数退出线程,并将需要传递给主线程的数据作为参数传递给pthread_exit函数。 5. 在主线程中,可以通过pthread_join函数获取线程T2的退出状态,并通过解引用参数指针来获取到传递给pthread_exit函数的数据。 总结起来,通过pthread_create函数传递参数给线程T2,线程T2通过解引用参数指针获取到传递的数据,并通过修改数据来与线程T1交换数据。线程T2执行完毕后,通过pthread_exit函数退出线程,并将需要传递给主线程的数据作为参数传递给pthread_exit函数。在主线程中,可以通过pthread_join函数获取线程T2的退出状态,并通过解引用参数指针来获取到传递给pthread_exit函数的数据。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Linux线程(2)——创建、终止和回收(pthread_create()、pthread_exit()、pthread_join())](https://blog.csdn.net/cj_lsk/article/details/130229709)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Linux线程编程(pthread_creat、pthread_exit、pthread_join、pthread_detach)](https://blog.csdn.net/weixin_42934918/article/details/114363789)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

因心,三人水

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

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

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

打赏作者

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

抵扣说明:

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

余额充值