当前位置: 首页 > news >正文

线程属性的相关设置详解

  1. pthread_attr_t 结构体

线程属性结构如下:

typedef struct
{
int                            detachstate;     //线程的分离状态
int                            schedpolicy;     //线程调度策略
struct sched_param    schedparam;    //线程的调度参数
int                            inheritsched;    //线程的继承性
int                            scope;             //线程的作用域
size_t                        guardsize;        //线程栈尾警戒缓冲区大小
int                             stackaddr_set;
void *                       stackaddr;       // 线程栈的位置
size_t                        stacksize;       // 线程栈的大小
}pthread_attr_t;

       detachstate,线程的分离状态决定一个线程以什么样的方式来终止自己。在默认情况下线程是非分离状态的,这种情况下,原有的线程等待创建的线程结束。只有当pthread_join() 函数返回时,创建的线程才算终止,才能释放自己占用的系统资源。分离线程没有被其他的线程所等待,自己运行结束了,线程也就终止了,马上释放系统资源。
通俗的说也就是:我们知道一般我们要等待(pthread_join)一个线程的结束,主要是想知道它的结束状态,否则等待一般是没有什么意义的!但是如果对一些线程的终止态我们压根就不想知道,那么就可以使用“分离”属性,那么我 们就无须等待管理,只要线程自己结束了,自己释放资源就可以。


detachstate有两种取值
  PTHREAD_CREATE_DETACHED:     分离状态启动
  PTHREAD_CREATE_JOINABLE:      聚合状态启动线程

schedpolicy,表示新线程的调度策略,主要包括:
SCHED_OTHER(正常、非实时)
SCHED_RR(实时、轮转法)
SCHED_FIFO(实时、先入先出)
缺省为SCHED_OTHER,

 schedparam,一个struct sched_param结构,目前仅有一个sched_priority整型变量表示线程的运行优先级。这个参数仅当调度策略为实时(即SCHED_RR或SCHED_FIFO)时才有效,

/usr/include /bits/sched.hstruct sched_param{int sched_priority;    //!> 参数的本质就是优先级};

注意:大的权值对应高的优先级!
                    系统支持的最大和最小的优先级值可以用函数:
                    sched_get_priority_max和sched_get_priority_min得到!

inheritsched,继承性决定调度的参数是从创建的进程中继承还是使用在 
schedpolicy和schedparam属性中显式设置的调度信息,

可设置参数:
            PTHREAD_INHERIT_SCHED: 新的线程继承创建线程的策略和参数!
            PTHREAD_EXPLICIT_SCHED:新的线程继承策略和参数来自于
 schedpolicy和schedparam属性中显式
设置的调度信息!

scope,表示线程间竞争资源的范围

POSIX的标准中定义了两个值:PTHREAD_SCOPE_SYSTEM和PTHREAD_SCOPE_PROCESS,

目前LinuxThreads仅实现了PTHREAD_SCOPE_SYSTEM一值。

scope有两种取值

PTHREAD_SCOPE_SYSTEM:    与系统中所有线程一起竞争资源      PTHREAD_SCOPE_PROCESS:     仅与同进程中的线程竞争CPU

示例:

 3. 线程属性及属性设置
3.1 线程属性结构体
typedef struct
{
int                            detachstate;     //线程的分离状态
int                            schedpolicy;     //线程调度策略
struct sched_param             schedparam;    //线程的调度参数
int                            inheritsched;    //线程的继承性
int                            scope;             //线程的作用域
size_t                         guardsize;        //线程栈尾警戒缓冲区大小
int                            stackaddr_set;
void *                         stackaddr;       // 线程栈的位置
size_t                         stacksize;       // 线程栈的大小
}pthread_attr_t;

    3.2. 线程属性设置流程
1)  初始化线程属性对象
pthread_attr_init
头文件:      #include <pthread.h>  
函数原型:    int pthread_attr_init(pthread_attr_t *attr);
函数功能:    初始化线程属性对象
函数参数:    attr:待初始化的线程属性对象
函数返回值:  成功返回0
失败返回错误码                
2)  设置指定的属性
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);

          3)  利用属性创建线程
4)  回收线程属性对象
pthread_attr_destroy
头文件:      #include <pthread.h>  
函数原型:    int pthread_attr_destroy(pthread_attr_t *attr);
函数功能:    回收线程属性对象
函数参数:    attr:待回收的线程属性对象
函数返回值:  成功返回0
失败返回错误码

#include <unistd.h>      // 提供Unix系统调用
#include <pthread.h>     // 多线程编程
#include <stdio.h>       // 标准输入输出
#include <string.h>      // 字符串处理
#include <stdlib.h>      // 标准库函数int thread_num = 0;      // 全局变量,用于线程计数// 线程执行函数
void* routine(void* argp)
{thread_num--;        // 线程结束时减少计数return NULL;         // 线程正常退出
}int main(int argc, char** argv)
{// 声明线程属性变量pthread_attr_t attr;// 初始化线程属性变量pthread_attr_init(&attr);// 获取和设置线程栈大小size_t stacksize = 0;// 设置线程栈大小为4MBpthread_attr_setstacksize(&attr, 4 * 1024 * 1024);// 获取实际设置的栈大小pthread_attr_getstacksize(&attr, &stacksize);printf("缺省线程栈空间大小:%lu MB\n", stacksize / 1024 / 1024);// 设置线程为分离状态(detached)pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);// 创建线程,使用自定义属性pthread_t id;pthread_create(&id, &attr, routine, NULL);thread_num++;       // 增加线程计数// 销毁线程属性变量(释放资源)pthread_attr_destroy(&attr);/*// 被注释的代码:尝试等待分离线程(会失败)int error = 0;if(error = pthread_join(id, NULL)){printf("join:%s\n", strerror(error));}*/// 忙等待,直到线程计数为0while(thread_num)   ;return 0;
}

关键机制详解

1. 线程属性设置

pthread_attr_t attr;
pthread_attr_init(&attr);  // 初始化属性对象

2. 栈大小设置

pthread_attr_setstacksize(&attr, 4 * 1024 * 1024);  // 设置为4MB
pthread_attr_getstacksize(&attr, &stacksize);       // 验证设置

栈大小说明:

  • 默认栈大小通常为2-10MB,取决于系统和编译器

  • 设置更大的栈用于需要大量局部变量的线程

  • 设置更小的栈用于创建大量线程的场景

3. 线程分离状态

pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

分离状态 vs 可连接状态:

状态特点是否需要pthread_join资源回收
PTHREAD_CREATE_JOINABLE (默认)可等待线程结束需要手动调用pthread_join回收
PTHREAD_CREATE_DETACHED分离状态不能等待自动回收资源

4. 被注释的pthread_join代码

/*
if(error = pthread_join(id, NULL))
{printf("join:%s\n", strerror(error));
}
*/

这里被注释是有原因的:

  • 线程被设置为分离状态后,不能再调用 pthread_join()

  • 如果取消注释,会返回 EINVAL 错误

5. 线程同步机制

while(thread_num) ;  // 忙等待,直到thread_num为0

工作原理:

  • 主线程创建子线程时:thread_num++ (变为1)

  • 子线程结束时:thread_num-- (变为0)

  • 主线程在忙等待循环中检测到这个变化后退出

程序执行流程

  1. 主线程初始化属性,设置栈大小和分离状态

  2. 主线程创建分离线程,增加线程计数

  3. 主线程进入忙等待循环

  4. 子线程执行,减少线程计数

  5. 子线程退出,系统自动回收资源(因为是分离线程)

  6. 主线程检测到thread_num为0,退出循环

  7. 程序结束

潜在问题和改进

1. 忙等待(Busy Waiting)问题

while(thread_num) ;  // CPU占用率高

改进方案:使用条件变量

#include <pthread.h>pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;void* routine(void* argp) {pthread_mutex_lock(&mutex);thread_num--;pthread_cond_signal(&cond);pthread_mutex_unlock(&mutex);return NULL;
}// 主线程中:
pthread_mutex_lock(&mutex);
while(thread_num) {pthread_cond_wait(&cond, &mutex);
}
pthread_mutex_unlock(&mutex);

2. 内存排序问题

thread_num--;  // 可能存在可见性问题

改进方案:使用原子操作或互斥锁

#include <stdatomic.h>
atomic_int thread_num = 0;// 或者使用互斥锁保护

3. 完整的改进版本

#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int thread_num = 0;void* routine(void* argp) {pthread_mutex_lock(&mutex);thread_num--;printf("子线程结束,剩余线程数: %d\n", thread_num);pthread_cond_signal(&cond);pthread_mutex_unlock(&mutex);return NULL;
}int main() {pthread_attr_t attr;pthread_attr_init(&attr);// 设置线程属性pthread_attr_setstacksize(&attr, 4 * 1024 * 1024);pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);// 创建线程pthread_t id;pthread_mutex_lock(&mutex);pthread_create(&id, &attr, routine, NULL);thread_num++;printf("创建线程,当前线程数: %d\n", thread_num);pthread_mutex_unlock(&mutex);// 等待线程结束pthread_mutex_lock(&mutex);while(thread_num > 0) {pthread_cond_wait(&cond, &mutex);}pthread_mutex_unlock(&mutex);pthread_attr_destroy(&attr);printf("所有线程结束,程序退出\n");return 0;
}

这个程序很好地演示了线程属性的使用,特别是栈大小设置和分离状态的配置。

http://www.dtcms.com/a/430803.html

相关文章:

  • 深圳公明网站建设桂林北站到阳朔
  • maven的概述以及在mac安装配置
  • 【复习】计网强化第一章
  • 【微信公众平台】小程序如何查找菜单?如何通过自定义的菜单路径生成小程序二维码?小程序二维码指定生成
  • 瑞萨M85内核芯片再出1GHz旗舰双核新品RA8T2,两个千兆以太网MAC,集成EtherCAT从机接口,面向高端电机控制
  • 海洋公园网站建设方案网站开发加设计要多少钱
  • KingbaseES 的 SQL Server 兼容性测试
  • 基于ps2021实现1寸相纸的打印
  • [论文阅读] AI + 软件工程 | 从“事后补救”到“实时防控”,SemGuard重塑LLM代码生成质量
  • 购物网站修改文案常见的网络推广方法有几种
  • 手腕鼓包?可能是腱鞘囊肿
  • 网站推广方法有网站制作哪家做的好
  • Servlet 国际化
  • 安卓基础组件016--Toas组件
  • InfiniBand技术解析(2):为什么它是高性能计算的 “超级血管”?
  • 微商本地化发展模式的借鉴与探讨——以开源AI智能名片链动2+1模式S2B2C商城小程序为例
  • 基于遗传优化的LSTM-Attention一维时间序列预测算法matlab仿真
  • 深圳公司 网站建设广州做网站公司哪家好
  • 多个wordpress网站合并成品源码1688网站免费
  • macOS/Linux ClaudeCode 安装指南及 Claude Sonnet 4.5 介绍
  • [创业之路-640]:通信行业供应链 - 通信网的发展趋势:IP化统一 、云网融合 、算网协同 、FMC(固定移动融合)、空天地一体化
  • IP 地址管理:IPv4 和 IPv6 地址规划、子网划分与 CIDR
  • router-id <ip-address> 概念及题目
  • Linux应用(6)——网络通信/TCP/IP
  • tcpdump总结
  • 小商品网站建设注册一个公司一年需要多少钱
  • 新奇特:神经网络的自洁之道,学会出淤泥而不染
  • tkinter+pymupdf开发的简单pdf查看编辑器
  • 给公司做网站和公众号需要多少钱如何注册网站名称
  • LeetCode 1039.多边形三角剖分的最低得分:记忆化搜索(深度优先搜索)