线程(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语言实战 #马年开工学习

相关推荐
vortex59 小时前
现代 Linux 包管理全景:从 apt 到 Nix,四大派系与四大范式
linux·运维·服务器
曦夜日长9 小时前
Linux系统篇,开发工具(四):make及makefile的使用、makefile的使用细节
linux·运维·服务器
历程里程碑10 小时前
54 深入解析poll多路复用技术
java·linux·服务器·开发语言·前端·数据结构·c++
Irene199110 小时前
Linux 默认权限详解:目录(755)与普通文件(644)权限机制,默认权限由 umask 值决定
linux·权限位
小小de风呀10 小时前
de风——【从零开始学习Linux】Linux基础指令详解(一)
linux·运维·服务器
蜡笔婧萱10 小时前
Linux---web服务器与DNS域名解析服务器的综合挑战
linux·运维·服务器
zandy101110 小时前
hermes agent 安装教程 3.0:Win / Mac / Linux 全平台指南
linux·运维·macos
.千余10 小时前
【Linux 】网络基础1
linux·运维·服务器·开发语言·网络·学习
IMPYLH10 小时前
Linux 的 uniq 命令
linux·运维·服务器·bash
Languorous.11 小时前
Linux 登录用户、主机名、提示符详解(新手不迷路)
linux·数据库·postgresql