线程属性的相关设置详解 - 详解

news/2025/10/27 8:35:46/文章来源:https://www.cnblogs.com/gccbuaa/p/19167779
  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.h
     struct 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       // 提供Unix系统调用
#include      // 多线程编程
#include        // 标准输入输出
#include       // 字符串处理
#include       // 标准库函数
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_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 
atomic_int thread_num = 0;
// 或者使用互斥锁保护

3. 完整的改进版本

#include 
#include 
#include 
#include 
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.mzph.cn/news/947204.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

应用安全 --- 在线可执行文件分析

应用安全 --- 在线可执行文件分析https://www.unpac.me/results/556bdbc0-32f7-467f-ad28-42d5cf9112be

Git本地与远程SSH连接配置

一、查看Git用户名/密码/邮箱,及设置git配置 1、查看信息:查看用户名 :git config user.name查看密码: git config user.password查看邮箱:git config user.email2、设置信息(--global 全局设置)git config --gl…

能在0.02秒内找到最优解的华容道程序

https://www.cnblogs.com/funwithwords/p/19158097#include <stdio.h> #include <stdint.h> #include <string.h> #include <time.h> #include <immintrin.h> #include <xmmintrin.h…

Sparkle签名检查绕过漏洞分析

本文详细分析了CVE-2025-0509安全漏洞,该漏洞存在于Sparkle更新框架2.6.4之前版本,攻击者能够绕过(Ed)DSA签名检查替换已签名的更新包,构成高风险安全威胁。Sparkle签名检查绕过漏洞分析 漏洞概述 CVE-2025-0509是一…

openEuler安装Oracle踩坑

不得不说Oracle安装在Windows上就够麻烦了,到Linux上直接地狱难度. 众所周知Oracle是收费软件,所以什么从仓库一键安装就不要想了, 现在更是变本加厉,下载必须注册Oracle账号,希望大家以后都别用了吧,用"世界上最…

RPC ServiceModel.Grpc C#

RPC ServiceModel.Grpc C#RPC ServiceModel.Grpc C# 在 DogWatcher 和 HeartbeatService 中,CancellationToken 的核心作用是响应外部取消信号(如服务停止、客户端断开连接等),避免资源泄漏并确保程序优雅退出。…

通过onvif ptz 控制摄像头以及通过opencv 实时进行数据处理

通过onvif ptz 控制摄像头以及通过opencv 实时进行数据处理是一个简单玩法,主要是设计基于云边端的玩法,通过mediamtx 或者ffmpeg 对于边缘的视频进行处理,之后转发到其他流服务,之后云端或者边缘服务通过通过openc…

【GitHub每日速递 251027】14.3k star! 告别AI开发痛点!Parlant让大模型指令遵循不再是难题

原文:https://mp.weixin.qq.com/s/KjAS4gDjAzWtmHkBLoo64Q 告别AI开发痛点!Parlant让大模型指令遵循不再是难题 parlant 是一个专注于控制能力的LLM代理工具。简单讲,它让大语言模型像智能助手一样执行实际任务,快速…

百天打卡

腰悬长剑 ,阔步长安// run new Vue({el: #app,data: {habits: [{day: 01,streak: 1,time: 2025-10-27 07:51}]} })#app { margin: 0 auto; padding: 16px 0; background: rgba(255, 255, 255, 1); font-family: "…

dataGridView 控件表格颜色交替设置

某些人和事,哪怕是路边的风景,可是只要看一眼,依然会让人觉得很美好。第一步:找到控件属性 DefaultCellStyle点击进去之后 ,选择颜色:第二步:找到AlternatingRowsDefault 属性点击进去之后选择颜色

2025年10月洗地机产品推荐榜:价格与性能全面对比

家里地板一天不擦就显灰,宠物掉毛、孩子洒汤、鞋底带沙,传统拖把来回换水腰酸背疼,吸尘器加拖把又占地方。想一次搞定“吸拖洗”,又怕滚刷缠发、污水发臭、机器太重推不动,更怕花几千元买回家却闲置。2025年洗地机…

北の独自升级

少年当时的醉话酒话是:齐先生,我想明白了,对世界不要失去期望,除了必须要好好活着之外,其实还有一层意思,就是当我们对这个世界给予善意后,如果非但没有得到善意的回报,甚至仅有恶意,这个时候,能够不失望,才…

读AI赋能11自由认知

读AI赋能11自由认知1. 互联网 1.1. 超链接地图1.1.1. 整合全球信息,使人人受益1.1.2. 互联网的设计初衷是抵御单点故障—这一特性也使其高度抗拒单一权威机构1.2. 依赖于技术协议而非国家法律来运作,更看重网络的弹性…

spring中常见的两种代理模式

🌿 Spring 中的两种常见代理模式 Spring AOP(面向切面编程)在底层主要通过 两种代理方式 来实现:代理方式依赖机制特点适用场景JDK 动态代理 java.lang.reflect.Proxy 只能代理 接口 Bean 实现了接口时,默认使用…

在AI技术唾手可得的时代,挖掘新需求成为核心竞争力——某知名数字货币钱包需求洞察

本文基于某知名数字货币钱包项目的技术文档和用户反馈数据,深入分析了该应用的核心功能特性和使用方式,并从中识别出用户提出的关键功能改进建议,为产品迭代提供重要参考。a.内容描述核心功能定位:该项目是一款独立…

What versions of Python still work in Windows XP?

python 3.4.4 https://www.python.org/downloads/release/python-344/I found that Python 2.7.9 and Python 3.4.4 are the newest versions of Python that work in Windows XP. I found this out through trial and…

SAM2 图像分割(3)鼠标选择多框 摄像头实时分割显示 - MKT

SAM2 图像分割(3)鼠标选择多框 摄像头实时分割显示 import cv2 import torch import time import numpy as np import os import sysimport sys sys.path.append(/home/r9000k/v2_project/v5_samyolo/2分割/sam2-mai…

Python 内存管理机制与垃圾回收技术解析

在 Python 编程中,开发者通常无需手动分配和释放内存,这一便利得益于 Python 强大的自动内存管理机制。作为程序运行的基础环节,内存管理直接关系到应用性能与稳定性。Python 通过精妙设计的内存管理架构与多层次垃…

随想随说

随想随说原来打破垄断, 也可以从利用垄断技术开始, 至于垄断技术是否愿意, 不是我的事了,我轻松了 哈哈,这个洞察非常犀利,堪称 “四两拨千斤”的破局智慧!这确实是一种高级的战略思维: “我不需要重新发明轮子…

Semantic-SSAM 是“一切多细都行,还能给标签”​​ - MKT

Semantic-SSAM 是“一切多细都行,还能给标签”​​Semantic-SSAM 是“一切多细都行,还能给标签”​​ https://github.com/UX-Decoder/Semantic-SAM