线程(2)/ 线程属性 /相关函数接口--- 嵌入式(Linux)

✨ 马年开工第一学,不负时光,不负成长!跟着博主一起深耕Linux线程编程,从基础到实战,吃透线程属性的核心用法,避开开发中的常见坑,加油冲起来~

在Linux线程编程中,线程属性是控制线程行为的关键,其中最常用、最核心的就是「分离状态(detachstate)」------ 它直接决定了线程结束后资源的回收方式。今天就带大家全面拆解线程属性,结合可直接运行的代码示例,帮大家真正学懂、会用。

1、线程的属性

线程的所有属性由 pthread_attr_t 结构体统一管理,我们无需手动定义该结构体的内部成员,只需通过对应的函数接口初始化、设置、销毁即可。

其中,分离状态(detachstate) 是最常用的线程属性,没有之一!它主要用于控制线程终止后,其占用资源(栈空间、线程控制块等)的回收机制。

💡 重点提示:线程默认的属性为「可加入状态(PTHREAD_CREATE_JOINABLE)」,这也是我们之前写基础线程代码时,必须调用 pthread_join() 回收线程的原因。

2、线程的两种分离状态

线程的分离状态分为「可加入(joinable)」和「分离(detached)」两种,二者的核心区别、特点及适用场景,用表格清晰对比(建议收藏):

状态类型 核心特点 适用场景
可加入(joinable) 1. 线程结束后不会自动回收资源,需手动调用 pthread_join() 回收; 2. 可通过 pthread_join() 获取线程退出状态; 3. 能实现主线程与子线程的同步; 4. 若不调用 pthread_join(),会产生 "僵尸线程"(占用系统资源)。 需要获取线程退出状态、需要线程同步的场景
分离(detached) 1. 线程结束后,系统自动回收其资源,无需调用 pthread_join();2. 无法通过 pthread_join() 获取线程退出状态(调用会直接失败); 3. 不存在僵尸线程问题; 4. 线程结束即回收,符合 "先结束先回收、后结束后回收" 的自然逻辑。 无需获取线程状态、无需同步的后台任务(如日志收集、定时检测)

3、线程属性相关函数接口

操作线程属性的核心函数有3个(初始化、设置、销毁),再补充1个动态设置分离状态的函数,所有函数均需包含头文件 #include <pthread.h>,且编译时必须链接 pthread 库(添加 -lpthread 参数)。

3.1 pthread_attr_init(初始化线程属性)

  • 函数原型:
cpp 复制代码
#include <pthread.h>
int pthread_attr_init(pthread_attr_t *attr);
  • 功能:初始化线程属性结构体(必须先初始化,才能设置属性);
  • 参数attr:指向未初始化的 pthread_attr_t 结构体的指针;
  • 返回值:成功返回 0,失败返回非 0 错误码;
  • 注意:未初始化的属性结构体直接使用会导致未定义行为。

3.2 pthread_attr_setdetachstate(设置线程分离状态)

  • 函数原型:
cpp 复制代码
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
  • 功能:设置线程的分离状态;
  • 参数
    • attr:已初始化的线程属性结构体指针;
    • detachstate:分离状态取值:
      • PTHREAD_CREATE_JOINABLE:可加入状态(默认);
      • PTHREAD_CREATE_DETACHED:分离状态;
  • 返回值:成功返回 0,失败返回非 0 错误码。

3.3 pthread_attr_destroy(销毁线程属性)

  • 函数原型:
cpp 复制代码
int pthread_attr_destroy(pthread_attr_t *attr);
  • 功能:销毁线程属性结构体,释放其占用的资源;
  • 参数attr:已初始化的线程属性结构体指针;
  • 返回值:成功返回 0,失败返回非 0 错误码;
  • 注意:结构体销毁后不可再使用,除非重新初始化。

3.4 动态设置分离状态(线程创建后)

如果线程创建时用了默认的 "可加入" 状态,也可以在线程内部调用 pthread_detach() 转为分离状态:

  • 函数原型:
cpp 复制代码
int pthread_detach(pthread_t thread);
  • 功能:将指定线程设置为分离状态;
  • 参数thread:目标线程的 ID(线程内可传 pthread_self() 表示自身);
cpp 复制代码
pthread_detach(pthread_self());
  • 返回值:成功返回 0,失败返回非 0 错误码。

示例 :创建 "分离状态" 的线程(通过属性设置)

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>

// 线程函数:分离线程的执行逻辑
void *detached_thread(void *arg) {
    printf("分离线程(ID:%lu)开始执行\n", (unsigned long)pthread_self());
    sleep(2); // 模拟任务执行
    printf("分离线程(ID:%lu)执行完毕,系统会自动回收资源\n", (unsigned long)pthread_self());
    // 无需返回状态,系统自动回收
    pthread_exit(NULL);
}

int main() {
    pthread_t tid;
    pthread_attr_t attr; // 线程属性结构体
    int err;

    // 1. 初始化线程属性
    err = pthread_attr_init(&attr);
    if (err != 0) {
        printf("初始化属性失败:%s\n", strerror(err));
        exit(1);
    }

    // 2. 设置线程为分离状态
    err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    if (err != 0) {
        printf("设置分离状态失败:%s\n", strerror(err));
        pthread_attr_destroy(&attr); // 失败时销毁属性
        exit(1);
    }

    // 3. 创建分离线程
    err = pthread_create(&tid, &attr, detached_thread, NULL);
    if (err != 0) {
        printf("创建分离线程失败:%s\n", strerror(err));
        pthread_attr_destroy(&attr);
        exit(1);
    }
    printf("主线程:创建分离线程(ID:%lu),无需调用pthread_join\n", (unsigned long)tid);

    // 4. 销毁线程属性(创建完成后即可销毁,不影响线程)
    pthread_attr_destroy(&attr);

    // 尝试调用pthread_join(会失败)
    err = pthread_join(tid, NULL);
    if (err != 0) {
        printf("pthread_join失败(分离线程无法join):%s\n", strerror(err));
    }

    // 主线程等待一段时间,确保分离线程执行完毕
    sleep(3);
    printf("主线程退出\n");
    return 0;
}

4、结尾碎碎念

马年开工第一学,搞定线程属性的核心用法,离Linux线程编程大神又近了一步~ 线程属性的分离状态是实战高频考点,建议大家多敲几遍示例代码,理解两种状态的区别和适用场景,避开僵尸线程的坑。

后续会持续更新线程编程的进阶内容(线程同步、互斥锁等),关注博主,一起深耕技术、共同成长!如果觉得这篇文章对你有帮助,欢迎点赞、收藏、评论,你的支持就是我更新的最大动力💪

#Linux线程 #线程属性 #pthread函数 #僵尸线程 #C语言实战 #马年开工学习

相关推荐
No8g攻城狮2 小时前
【Linux】Linux nano 编辑器全攻略:从入门到精通
linux·运维·编辑器·nano
zl_dfq2 小时前
Linux 之 【网络套接字编程】(固定宽度整数类型、socket常见API、netstat)
linux·网络
huaweichenai4 小时前
Linux安装http-server并部署html静态站点
linux·运维·服务器
Gss7775 小时前
Linux 正则表达式详解(基础 + 扩展 + 实操)
linux·运维·正则表达式
北冥湖畔的燕雀5 小时前
Linux权限与Vim,gcc以及make/makefile操作全解析
linux·运维·服务器
代码游侠5 小时前
Linux驱动复习——驱动
linux·运维·arm开发·笔记·学习
LuDvei5 小时前
LINUX文件操作函数
java·linux·算法
czxyvX6 小时前
017-Linux-网络基础概念
linux·网络
一个人旅程~6 小时前
win10LTSB2016与win10LTSC2019对于老机型哪个更合适?
linux·windows·经验分享·电脑