Linux多线程(六)之线程控制4【线程ID及进程地址空间布局】

article/2025/7/4 5:47:31

文章目录

      • 线程ID及进程地址空间布局
        • 线程局部存储

线程ID及进程地址空间布局

  1. pthread_ create函数会产生一个线程ID,存放在第一个参数指向的地址中。

    该线程ID和前面说的线程ID不是一回事。

  2. 前面讲的线程ID属于进程调度的范畴。

​ 因为线程是轻量级进程,是操作系统调度器的最小单位,

​ 所以需要一个数值来唯一表示该线程。

​ 用户级线程+内核轻量级进程=Linux线程

​ 线程:用户级线程、内核级线程

Linux线程就是用户级线程

​ 用户级执行流:内核lwp = 1:1

  1. pthread_ create函数第一个参数指向一个虚拟内存单元,

​ 该内存单元的地址即为新创建线程的线程ID,属于NPTL线程库的范畴。

​ 线程库的后续操作,就是根据该线程ID来操作线程的。

  1. 线程库NPTL提供了pthread_ self函数,可以获得线程自身的ID:
pthread_t pthread_self(void);

pthread_self

#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <thread>
#include <string>
#include <cstdlib>using namespace std;string tohex(pthread_t tid)
{char hex[64];snprintf(hex, sizeof(hex), "%p", tid);return hex;
}void *threadroutine(void *args)
{while (1){cout << "thread id: " << tohex(pthread_self()) << endl;sleep(1);}
}int main()
{pthread_t tid;pthread_create(&tid, nullptr, threadroutine, (void *)"thread 1");cout << "main thread create thread done,new thread id: " << tohex(tid) << endl;pthread_join(tid, nullptr);return 0;
}

image-20250429132415068

pthread_t 到底是什么类型呢?取决于实现。

对于Linux目前实现的NPTL实现而言,pthread_t类型的线程ID,

本质就是一个进程地址空间上的一个地址。

image-20250425230334017

一个执行流本质就是一条调用链。

调用函数就是在栈帧中为该函数形成栈帧结构。

为了完成临时变量空间在栈帧中的开辟和释放。

验证创建多线程:

makefile

mythread:mythread.ccg++ -o $@ $^ -std=c++11 -lpthread
.PHONY:clean
clean:rm -rf mythread

mythread.cc

#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <cstring>
#include <cstdlib>
#include <vector>using namespace std;#define NUM 5struct threadData
{string tname;
};string toHex(pthread_t tid)
{char buffer[1024];snprintf(buffer, sizeof(buffer), "0x%x", tid);return buffer;
}void InitThreadData(threadData *td, int i)
{td->tname = "thread-" + to_string(i);
}void *threadRoutine(void *args)
{threadData *td = static_cast<threadData *>(args);int i = 0;while (i < 5){cout << "pid: " << getpid() << " ,tid: " << toHex(pthread_self()) << " ,name: " << td->tname << endl;sleep(1);i++;}delete td;return nullptr;
}int main()
{vector<pthread_t> tids;for (int i = 0; i < NUM; i++){pthread_t tid;threadData *td = new threadData;// 使用堆空间 而且每次都是新的堆空间 堆空间是共享的 访问的是堆空间的不同位置// 我们让一个线程访问对应的一个堆空间InitThreadData(td, i);pthread_create(&tid, nullptr, threadRoutine, td);tids.push_back(tid);sleep(1);}for (int i = 0; i < NUM; i++){pthread_join(tids[i], nullptr);}return 0;
}

image-20250505145912944

验证每个线程都有独立的栈结构:

void *threadRoutine(void *args)
{int test_i=0;threadData *td = static_cast<threadData *>(args);int i = 0;while (i < 5){cout << "pid: " << getpid() << " ,tid: " << toHex(pthread_self()) << " ,name: " << td->tname <<" ,test_i: "<<test_i<<" ,&test_i: "<<toHex((pthread_t)&test_i)<< endl;sleep(1);i++,test_i++;}delete td;return nullptr;
}

image-20250505151208228

验证每个线程的栈数据是可以被访问的(但是不建议):

#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <cstring>
#include <cstdlib>
#include <vector>using namespace std;#define NUM 5int*p;struct threadData
{string tname;
};string toHex(pthread_t tid)
{char buffer[1024];snprintf(buffer, sizeof(buffer), "0x%x", tid);return buffer;
}void InitThreadData(threadData *td, int i)
{td->tname = "thread-" + to_string(i);
}void *threadRoutine(void *args)
{int test_i=0;threadData *td = static_cast<threadData *>(args);int i = 0;if(td->tname=="thread-0"){p=&test_i;}while (i < 5){cout << "pid: " << getpid() << " ,tid: " << toHex(pthread_self()) << " ,name: " << td->tname <<" ,test_i: "<<test_i<<" ,&test_i: "<<&test_i<< endl;sleep(1);i++,test_i++;}delete td;return nullptr;
}int main()
{vector<pthread_t> tids;for (int i = 0; i < NUM; i++){pthread_t tid;threadData *td = new threadData;// 使用堆空间 而且每次都是新的堆空间 堆空间是共享的 访问的是堆空间的不同位置// 我们让一个线程访问对应的一个堆空间InitThreadData(td, i);pthread_create(&tid, nullptr, threadRoutine, td);tids.push_back(tid);// sleep(1);}sleep(1);//确保赋值成功cout<<"main thread get a thread local value,val: "<<*p<<" ,&val: "<<p<<endl;for (int i = 0; i < NUM; i++){pthread_join(tids[i], nullptr);}return 0;
}

image-20250505155535503

线程与线程之间几乎没有秘密

线程栈上的数据,也是可以被其他线程看到并访问的。

线程局部存储
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <cstring>
#include <cstdlib>
#include <vector>using namespace std;#define NUM 5int g_val=0;struct threadData
{string tname;
};string toHex(pthread_t tid)
{char buffer[1024];snprintf(buffer, sizeof(buffer), "0x%x", tid);return buffer;
}void InitThreadData(threadData *td, int i)
{td->tname = "thread-" + to_string(i);
}void *threadRoutine(void *args)
{threadData *td = static_cast<threadData *>(args);int i = 0;while (i < 5){cout << "pid: " << getpid() << " ,tid: " << toHex(pthread_self()) << " ,name: " << td->tname <<" ,g_val: "<<g_val<<" ,&g_val: "<<&g_val<< endl;sleep(1);i++,g_val++;}delete td;return nullptr;
}int main()
{vector<pthread_t> tids;for (int i = 0; i < NUM; i++){pthread_t tid;threadData *td = new threadData;InitThreadData(td, i);pthread_create(&tid, nullptr, threadRoutine, td);tids.push_back(tid);// sleep(1);}for (int i = 0; i < NUM; i++){pthread_join(tids[i], nullptr);}return 0;
}

image-20250505160424955

全局变量是被所有的线程同时看到并访问的。

如果线程想要一个私有的全局变量呢??

__thread+变量
__thread int g_val=0;

image-20250505161121658

编译器提供的编译选项

__thread threadData td;

image-20250505161425635

__thread只能用来定义内置类型,不能用来定义自定义类型

作用:可以存储该线程的某些系统调用数据(就不需要频繁调用的系统调用了)。

__thread unsigned int number=0;
__thread int pid=0;struct threadData
{string tname;
};void *threadRoutine(void *args)
{pid=getpid();number=pthread_self();threadData *td = static_cast<threadData *>(args);int i = 0;while (i < 5){cout<<"pid: "<<pid<<" ,tid: "<<number<<endl;sleep(1);i++,g_val++;}delete td;return nullptr;
}

image-20250505162435763

在调用链上,可以直接获取该线程的pid、tid等。(线程级别的全局变量而且互不干扰)


http://www.hkcw.cn/article/GFMcsUhfSt.shtml

相关文章

美政府终止一项艾滋病疫苗研发项目 抗击艾滋病努力受挫

特朗普政府终止了一项2.58亿美元的项目,对艾滋病疫苗研发工作造成了沉重打击。一位不愿透露姓名且未经授权发言的高级官员表示,美国国立卫生研究院计划将关注点转向利用现有方法消除艾滋病,并暂停了莫德纳公司研发的一项艾滋病疫苗临床试验。公共卫生专家指出,这些削减措施…

俄称击落千余架乌军无人机 俄军攻势持续

5月30日,俄罗斯国防部发布战报称,在过去一周里,俄军对乌克兰境内的国防工业设施、军用机场基础设施、武器弹药储存设施等目标实施了打击。在苏梅、哈尔科夫、顿涅茨克等地,俄军打退了乌军多次进攻并发动攻势。俄防空部队击落了1439架固定翼无人机,并控制了苏梅、哈尔科夫、…

于正称大师算出横店爆剧为《藏海传》 热度断层登顶破纪录

于正曾透露,他找大师算出的横店爆剧是《藏海传》。他在文中提到,大师通过塔罗牌预测,爆剧会与5、7、9这三个数字有关。而肖战恰好是5号出生,姓氏“肖”有7画,名字“战”有9画,这似乎正好对应了《藏海传》。《藏海传》自上线以来,热度迅速攀升,仅38小时就打破了站内热度…

上交解锁遥感图像中的空间理解能力!AirSpatialBot:面向细粒度车辆属性识别与检索的空间感知空中智能体

作者&#xff1a;Yue Zhou 1 ^{1} 1, Ran Ding 1 ^{1} 1, Xue Yang 2 ^{2} 2, Xue Jiang 1 ^{1} 1, Xingzhao Liu 1 ^{1} 1单位&#xff1a; 1 ^{1} 1上海交通大学电子工程系&#xff0c; 2 ^{2} 2上海交通大学自动化系论文标题&#xff1a;AirSpatialBot: A Spatially-Aware A…

dvwa3——CSRF

LOW&#xff1a; 先尝试change一组密码&#xff1a;123456 修改成功&#xff0c;我们观察上面的url代码 http://localhost/DVWA/vulnerabilities/csrf/?password_new123456&password_conf123456&ChangeChange# 将password_new部分与password_conf部分改成我们想要的…

论坛系统(4)

用户详情 获取用户信息 实现逻辑 ⽤⼾提交请求&#xff0c;服务器根据是否传⼊Id参数决定返回哪个⽤⼾的详情 1. 不传⽤⼾Id&#xff0c;返回当前登录⽤⼾的详情(从session获取) 2. 传⼊⽤⼾Id&#xff0c;返回指定Id的⽤⼾详情(根据用户id去查) 俩种方式获得用户信息 参…

CST-网格类型(六面体网格)

在CST软件中每种算法都非常适合特定类型的网格&#xff0c;如下所示&#xff1a; lHexahedral六面体网格&#xff0c;瞬态模拟&#xff08;T求解器&#xff09;时采用lHexahedral TLM传输线法时采用的网格划分lHexahedral (legacy)调整网格密度lTetrahedral四面体网格&#xff…

金价波动小克重金饰受欢迎 消费者倾向低风险购买

最近一段时间,国际金价波动加剧,年初以来最高涨幅接近30%,国内品牌首饰金价格一度突破每克千元。目前,金价有所回调,国内首饰金的批发价在每克近800元左右。面对金价波动,黄金消费市场出现了新变化。在北京的一家珠宝城柜台前,不少顾客正在挑选、询价。一位商家表示,尽…

韩国地铁纵火嫌疑人已被抓获 无人员伤亡报告

今天早上8时47分左右,韩国首尔地铁5号线一辆列车在途经汝矣渡口站前往麻浦站途中发生火灾。车厢内起火后,乘客迅速下车并通过地铁轨道疏散。纵火嫌疑人已被抓获,目前没有人员伤亡报告。责任编辑:zx0176

全国共有少先队员1.13亿名 最新统计数据发布

今天,全国少工委发布了中国少年先锋队的主要统计数据。截至2024年12月31日,全国共有少先队员1.13亿名,中小学校少先队大、中队辅导员305.4万名。此外,还有17.6万个中小学校少工委、17.9万个少先队大队和287.4万个中队。责任编辑:zx0176

让孩子远离“毒”“危”玩具 科学选购护航健康

给孩子挑选安全的玩具是许多家长关心的话题。随着“六一”国际儿童节的到来,如何帮助孩子远离有毒或危险的玩具,以及如何合理选购和安全使用玩具成为了讨论的焦点。近期,国家儿童医学中心、北京儿童医院急诊中心主任黄柳明接诊了一名3岁男童误吞“水精灵”的病例。“水精灵”…

特朗普媒体集团完成24.4亿美元融资 转向加密货币投资

特朗普媒体科技集团(DJT)宣布完成与约50家机构投资者的私募发行,消息公布后,DJT股价盘中一度上涨超过7%。公司以每股25.72美元的价格出售了5586万股普通股,筹集了14.4亿美元的资金。此外,通过发行2028年到期的零息可转债,又筹集了10亿美元资金。两项合计募资约24.4亿美元,…

案例回顾:累计下载700w+,点金石赋能娱乐场类手游实现规模与营收跃升!

回顾中国手游出海的发展历程&#xff0c;国产手游已在多个赛道实现突破。然而&#xff0c;受海外政策监管趋严以及品类自身属性限制&#xff0c;娱乐场类手游始终处于相对“低调”的发展状态。尽管该类产品商业价值已在市场得到验证&#xff0c;但在出海过程中仍面临诸多挑战—…

骨架工程—组织主数据管理

在集团化运营与多系统并行的背景下,组织主数据作为描述企业核心架构的“数字骨架”,直接影响财务核算、人力资源、供应链协同等关键流程。然而,组织架构频繁调整、数据分散冗余、系统集成困难等问题,正成为企业高效运转的隐形障碍。本文将深入解析组织主数据的管理逻辑与破…

陪诊小程序开发,让就医陪伴触手可及

就医&#xff0c;对于每个人来说都是一件重要但又可能充满压力的事情。尤其是对于那些独自就医、行动不便或者对医院环境陌生的人来说&#xff0c;更需要有人陪伴和帮助。陪诊小程序开发&#xff0c;让就医陪伴触手可及&#xff0c;为患者带来更多的安心和温暖。 陪诊小程序打…

[yolov11改进系列]基于yolov11引入轻量级注意力机制模块ECA的python源码+训练源码

【ECA介绍】 ECA&#xff08;Efficient Channel Attention&#xff09;注意力机制是一种轻量级的通道注意模块&#xff0c;旨在通过简单而高效的方式增强模型囚对于不同特征通道之间依赖关系的学习能力。其核心思想是在不增加过多计算成本的情况下捕获跨通道的相关性和重要性差…

电动飞行器(eVTOL)动力测试实验室系统方案

◎动力测试实验室建设背景 随着全球能源结构调整和环保意识增强&#xff0c;电动飞行作为一种绿色、高效的航空交通工具&#xff0c;正成为未来航空产业发展的重要方向。近年来&#xff0c;电动飞行器技术取得突破性进展&#xff0c;电动垂直起降飞行器&#xff08;eVTOL&…

Spring Boot微服务架构(九):设计哲学是什么?

一、Spring Boot设计哲学是什么&#xff1f; Spring Boot 的设计哲学可以概括为 ​​“约定优于配置”​​ 和 ​​“开箱即用”​​&#xff0c;其核心目标是​​极大地简化基于 Spring 框架的生产级应用的初始搭建和开发过程​​&#xff0c;让开发者能够快速启动并运行项目…

autodl 安装了多个conda虚拟环境 选择合适虚拟环境的语句

1.conda env list 列出所有虚拟环境 可以看到&#xff0c;我有两个虚拟环境&#xff0c;一个是joygen&#xff0c;一个是base conda activate base 或者 conda activate joygen 激活对应的环境。我选择激活 joygen 环境 然后就可以在joygen环境下进行操作了 base环境也是同理…

私募18亿资金围猎ETF 投资热情高涨

在国内指数化投资蓬勃发展的背景下,私募基金配置ETF的热情不断增长。特别是大中型私募机构对ETF的购买行为十分明显。例如,量化私募铸锋资产和众壹资产在2025年内上市的ETF份额均超过1亿份;百亿级私募思勰投资和玄元投资则分别买入了5000.55万份和2300.01万份。截至2025年5月…