系统编程--线程

这里写目录标题

  • 线程概念
    • 什么是线程
      • 简介
      • 图解
    • 内核原理
      • 图解
    • 线程共享资源与非共享资源
      • 共享资源
      • 非共享资源
    • 线程优缺点
  • 线程控制原语
    • pthread_self、pthread_create
      • 简介
      • 代码
      • 总结
    • 循环创建多个子线程
      • 错误代码
    • 线程间全局变量共享
    • pthread_exit
      • 简介
      • 代码
  • 一级目录
    • 二级目录
    • 二级目录
    • 二级目录
  • 一级目录
    • 二级目录
    • 二级目录
    • 二级目录
  • 一级目录
    • 二级目录
    • 二级目录
    • 二级目录

线程概念

什么是线程

简介

在这里插入图片描述

图解

在这里插入图片描述
对于一个进程来说,他有独立的进程地址空间,如上图左侧0~4G的进程地址空间,且他有一个PCB进程控制块

而当该进程调用pthread_create()创建线程时,这个线程不会再有新的0~4G的进程地址空间,而是使用当前进程的地址空间,但是该线程会创建出一个自己的PCB控制块

在这里插入图片描述
而一旦一个进程创建出一个线程,该进程也叫做线程了,就相当于从一开始的整租->合租,虽然你是第一个租的,但由于有别人一起来租,你们俩就都叫合租

所以,进程是最小的内存的资源分配单位,而进程是最小的执行单位,可以把进程看做是一个只有一个线程的进程

关于线程影响单核CPU分配资源:
在这里插入图片描述
起初,我们有三个进程,这三个进程一开始是平等的,他们会平均的争夺CPU,而此时,如果A进程新建两个线程,一共三个线程,此时CPU就会把更多的时间片分给进程A,因为最小执行单元是线程而不是进程,所以,在CPU眼里,进程A的三个线程就是三个进程,他将平均的时间分配给进程A的三个线程时,就意味着把更多的时间片分配给了进程A

但是不要向一个进程内塞过多的线程,这样反而到达一定的峰值之后,物极必反

如下图,firefox的例子:
在这里插入图片描述
我们开启一个firefox时,可以使用ps -Lf pid 来查看当前进程的线程状态,可以看到,启动一次火狐,他就开了45个线程(利用线程池的原理),其中LWP列的编号为线程号,可以看到,线程号是继续上面的进程号的,所以,在CPU眼里,线程是最小的执行单元

总结:
在这里插入图片描述

内核原理

图解

在这里插入图片描述
先看右边,当进程地址空间向物理内存映射时,他的数据段与物理内存并不是直接通过MMU去映射,而是先映射到PCB中的一个“描述虚拟地址空间”的指针,之后再映射到MMU,然后再映射到物理内存地址

而右图中圆圈圈起来的那一步:即从PCB到物理内存的具体映射,看左边所示:
PCB有一根指针,之后该指针指向一个页面,页面指向页表,页表指向页目录,页目录就会映射物理地址
而此时如果创建一个线程,那么该线程就会创建出一个PCB,指向同样的页面,所以,一个进程中的线程的地址空间是共享的

而这里区分新创建的一个进程:
在这里插入图片描述
如果创建一进程而不是线程,那么此时就会被分配一块独立的资源,此时该进程的三级页表与之前进程的三级页表完全不同

总结:
在这里插入图片描述

线程共享资源与非共享资源

共享资源

在这里插入图片描述
1、文件描述符表共享
2、信号的处理方式共享,但是不同线程之间的mask是不共享的,因此可以利用这一点进行指定哪个线程接收信号
5、共享内存地址空间,但是不共享栈区(因为线程就是寄存器和栈的集合,每个线程有每个线程独立的栈空间)

非共享资源

在这里插入图片描述
2、处理器线程和内核栈:其实就是寄存器的值和内核的一个栈区
3、用户空间栈也不共享
所以,不管是内核还是用户空间栈,都不共享

4、errno,起初,errno变量是一个全局变量,但是对于线程来说,errno是不共享的,但是对于其他全局变量是共享的
5、信号屏蔽字mask

线程优缺点

在这里插入图片描述
对于优点的第三点:数据通信方便、共享数据方便,主要是由于不同的线程是在同一块资源地址空间内的,所以,对于数据来讲,除了栈不共享,其他区域数据都共享(全局变量区、堆区、…)

总结:
在这里插入图片描述

线程控制原语

pthread_self、pthread_create

简介

在这里插入图片描述
在这里插入图片描述

代码

在这里插入图片描述
我们称main函数中的线程是主线程
而之后创建的线程是子线程

在主线程中,我们使用pthread_create创建子线程,参数:
参数一:传出参数,表示所创建的子线程的线程ID(注意不是lwp中的线程号)
参数二:传入参数,表示线程属性,通常传NULL,表示使用线程的默认属性
参数三:线程运行函数,该函数返回值必须为void *,参数是一个指针
参数四:表示线程运行函数的参数,由于是使用泛型指针,所以传参时可以传单参,也可以多参(通过结构体指针)

这里我们先传NULL

返回值:成功:0,失败:返回errno(直接返回errno,而不是设置errno)

在线程运行函数中,同样的,我们打印线程的pid和tid

注意:
1、打印tid时,要使用%lu控制符,因为pthread_t是unsigned long类型
2、编译时,要加上-pthread选项,或者加上-lpthread(前面加小L),这是链接线程库
3、main函数创建完子线程之后,不能立马退出,因为所创建的线程要依赖于主线程的内存资源,主线程若结束,子线程的内存资源也就没了,所以可以让主线程sleep,晚结束一会儿,等子线程打印完之后,再结束,而在实习时,使用的是while,保证主线程不结束
4、子线程函数规定返回值必须为void *,所以我们return NULL

总结

在这里插入图片描述

循环创建多个子线程

错误代码

在这里插入图片描述
在这里插入图片描述
可以看到thread的编号都变成了6

错误分析:
在这里插入图片描述
由于线程是不共享栈的,所以,上面的代码中,我们取i的地址,而i是main函数的局部变量,所以,我们将i的地址传给线程函数后,线程函数会拿到一个main中局部变量的地址,解引用且拷贝其值,但是在线程解引用拷贝值的时候,i 已经 ++了,因为main中的for循环是一个无需任何资源介入,执行很快的动作,而线程调用需要进出内核,所以,在线程解引用拷贝值的时候,i 已经 ++了,甚至++了很多次

修改:
在这里插入图片描述
直接将值,转为void *,之后在线程函数中,再转回int
在64位系统中,int是4字节,指针是8字节,我们先将一个4字节的值给到一个8字节的变量存储,之后,再从这个8字节的变量强转为4字节的变量中存储,只要进的时候不会缺失数据,出的时候也不会,所以,是可行的,但是编译器可能会给出警告,但是是可以运行的

效果:
在这里插入图片描述
如果想要消除警告:
在这里插入图片描述

总结:
在这里插入图片描述

线程间全局变量共享

在这里插入图片描述
首先,主线程打印一下var变量的初始值

之后,创建子线程,在子线程中对全局变量进行修改,并打印,之后,主线程停一秒,目的是等待子线程执行完毕,最后,在主线程中打印一下当前var的值

效果:
在这里插入图片描述

pthread_exit

简介

在这里插入图片描述
最后一句话说的是不要返回局部变量的地址

代码

需求:假如说,我们想要第三个线程退出,而其他线程继续工作

方式一:
在这里插入图片描述
使用exit(0),表示正常退出

效果:
在这里插入图片描述
第3个以及后面的线程没有输出,这是因为exit表示的是进程退出,整个进程被退出的话,所有的线程也会被退出

而exit之前,已经有两个线程输出,exit之后,所有线程退出,不再会有输出

方式二:
在这里插入图片描述
使用return

效果:
在这里插入图片描述
可以实现

方式三:
在这里插入图片描述
使用带有return NULL的一个函数,显然是不行的,因为return只返回当前函数,返回到上一级,上图return的功能只能影响到func函数,无法影响到tfn函数

效果:
在这里插入图片描述
修正:
在这里插入图片描述
但是如果所调用的函数中含有pthread_exit(),那么就可以影响到外层的线程,让线程退出,且仅退出线程,而不退出进程

效果:
在这里插入图片描述

当然我们直接将其放到线程函数才是最常规的:
在这里插入图片描述

补充:
在这里插入图片描述
现在来看我们之前的一个问题,就是主线程只创建一个子线程,但是,如果主线程不sleep,会在子线程执行打印之前,主线程return,将main函数返回给调用者,就会把进程结束,从而子线程无法打印内容

现在,我们将sleep(1)去除,同时将return改为pthread_exit(NULL),这样,主线程退出不再使用进程退出,而是使用线程退出,那此时主线程退出就不会把进程退出,那么子线程也可以继续执行自己的内容了

效果:
在这里插入图片描述
主线程和子线程都打印了自己的内容,当所有线程结束时,进程也就结束了

总结:
在这里插入图片描述

一级目录

二级目录

二级目录

二级目录

一级目录

二级目录

二级目录

二级目录

一级目录

二级目录

二级目录

二级目录

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/873357.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

可持久化Trie详解,最大异或和,k大异或和

零、碎碎念 打比赛没遇上可持久化Trie,做个CMU 15-445的project0,上来就碰上了…… 关于Trie详见:[Trie树/字典树的原理及实现C/C]_trie字典树原理-CSDN博客 一、可持久化Trie 1.1 基本思想 可持久化Trie和可持久化线段树类似&#xff0c…

白小白为波司登新品创作歌曲《登峰之路》,穿越风雨守护前行者

随着天气渐凉,波司登品牌推出全新新品——轻薄羽绒叠变系列,作为波司登品牌的新品推荐官,歌手白小白为波司登创作并演唱《轻薄羽绒叠变》系列主题曲《登峰之路》。歌曲中,白小白以激昂澎湃,明快有力的旋律以及深情又充…

[数据集][目标检测]西红柿缺陷检测数据集VOC+YOLO格式17318张3类别

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):17318 标注数量(xml文件个数):17318 标注数量(txt文件个数):17318 标…

【第0006页 · 数组】寻找重复数

【前言】本文以及之后的一些题解都会陆续整理到目录中,若想了解全部题解整理,请看这里: 第0006页 寻找重复数 今天想讨论的一道题在 LeetCode 上评论也是颇为“不错”。有一说一,是道好题,不过我们还是得先理解了它才…

【Unity小技巧】URP管线遮挡高亮效果

前言 在URP渲染管线环境下实现物体遮挡高亮显示效果,效果如下:Unity URP遮挡高亮 实现步骤 创建层级,为需要显示高亮效果的物体添加层级,比如Player 创建一个材质球,也就是高亮效果显示的材质球找到Universal Render…

react项目搭建、基础知识

前言 教学内容来源于黑马 黑马程序员前端React18入门到实战视频教程,从reacthooks核心基础到企业级项目开发实战 项目搭建 创建项目 pnpm create vite选择框架 选择语言和构建 安装依赖并运行 pnpm install pnpm run dev运行成功 基础知识 文件 main…

极盾故事|某金融租赁机构应用数据保护新策略:“动态脱敏”“二次授权”

数据的流通使用是创新的动力,但安全和合规是不可逾越的底线。企业如何在这三者之间找到平衡点? 极盾科技,助力某金融租赁机构,基于极盾觅踪构建应用数据动态脱敏系统,实现10+核心应用系统的统一管理&#x…

磁电偶极子天线学习1 一种60GHz 宽带圆极化口径耦合磁电偶极子天线阵列

摘要: 一种新型的圆极化口径耦合天线被提出。这种圆极化磁电偶极子天线由刻蚀在短路基片集成波导的一部分的宽臂上,并且很容易被集成基片。在工作频段内实现了宽于28.8%的阻抗带宽和宽带3-dB的25.9%的轴比和的增益。此外,因为圆极化辐射由两个…

ModuleNotFoundError: No module named ‘mmcv.transforms‘

不得已的解决方法: mmcv升级到2.0.0即可解决 升级后自然又面临一系列不兼容问题! 官方文档查漏补缺

HNU-2023电路与电子学-实验3

写在前面: 本次实验是完成cpu设计的剩余部分,整体难度比上一次要小,细心完成就能顺利通过全部测评 一、实验目的 1.了解简易模型机的内部结构和工作原理。 2.分析模型机的功能,设计 8 重 3-1 多路复用器。 3.分析模型机的功能…

基于python的Selenium webdriver环境搭建(笔记)

一、PyCharm安装配置Selenium环境 本文使用环境:windows11、Python 3.8.1、PyCharm 2019.3.3、Selenium 3.141.0 测试开发环境搭建综述 安装python和pycharm安装浏览器安装selenium安装浏览器驱动测试环境是否正确 这里我们直接从第三步开始 1.1 Seleium安装…

Python Flask_APScheduler定时任务的正确(最佳)使用

描述 APScheduler基于Quartz的一个Python定时任务框架,实现了Quartz的所有功能。最近使用Flask框架使用Flask_APScheduler来做定时任务,在使用过程当中也遇到很多问题,例如在定时任务调用的方法中需要用到flask的app.app_context()时&#…

828华为云征文|使用sysbench对Mysql应用加速测评

文章目录 ❀前言❀测试环境准备❀测试工具选择❀测试工具安装❀mysql配置❀未开启Mysql加速测试❀开启Mysql加速测试❀总结 ❀前言 大家好,我是早九晚十二。 昨天有梳理一篇关于华为云最新推出的云服务器产品Flexus云服务器X。当时有说过,这次的华为云F…

一个好用的Maven依赖冲突解决插件:Maven Helper

在项目开发,或项目Maven需要新增依赖、项目依赖组件升级时,经常会出现添加后,因为各个模块中有相同的依赖、不同的版本而导致依赖冲突,从而导致项目启动不起来,这种冲突非常恶心,因为是传递依赖所以会看不出…

vulhub ThinkPHP5.0.23远程代码执行漏洞

1.在vulhub打开环境 进入环境存在的文件 docker-compose up -d 2.浏览器访问环境 3.查看是否存在漏洞 /index.php?scaptcha 页面报错说明有可能存在 4.使用hackbar插件发送post请求 _method__construct&filter[]system&methodget&server[REQUEST_METHOD]dir…

排查SQL Server中的内存不足及其他疑难问题

文章目录 引言I DMV 资源信号灯资源信号灯 DMV sys.dm_exec_query_resource_semaphores( 确定查询执行内存的等待)查询性能计数器什么是内存授予?II DBCC MEMORYSTATUS 查询内存对象III DBCC 命令释放多个 SQL Server 内存缓存 - 临时度量值IV 等待资源池 %ls (%ld)中的内存…

高通智能模组:以卓越优势引领科技潮流

一、高通智能模组的崛起与发展 在通信技术发展中,高通智能模组出现。5G 兴起,对模组有更高要求,高通凭借积累和创新捕捉需求。早期致力于研发 5G 技术,优化技术降低功耗提高处理能力,展现性能优势。在竞争中&#xff0…

剪映剪辑影视视频字幕声音批量自动对齐教程

一款智能软件,用它结合剪映或CapCut 你就可以快速将一个视频翻译为另一种语言,非常适合做TikTok中视频的用户,无论是英语区法语区还是日语区,这款名为谷哥剪映助手的软件都能成倍提升你的剪辑效率。 让我来给大家介绍它的使用方法…

基于移动互联网的校内物业报修管理系统设计与实现(论文+源码)_kaic

基于移动互联网的校内物业报修管理系统设计与实现 摘  要 校园后勤服务对于学校的发展至关重要,它不仅是学校管理的基石,也是实现教育目标的关键因素,为学生提供优质的生活环境。如果学校能够提供出色的后勤保障,让师生无需担心…

【自动驾驶】控制算法(七)离散规划轨迹的误差计算

写在前面: 🌟 欢迎光临 清流君 的博客小天地,这里是我分享技术与心得的温馨角落。📝 个人主页:清流君_CSDN博客,期待与您一同探索 移动机器人 领域的无限可能。 🔍 本文系 清流君 原创之作&…