线程互斥与同步

用户级线程 + 内核的LWP = Linux线程

OS概念中经常说的
用户级线程 和 内核级线程 也就是线程实现真的是在OS内部实现,还是应用层或用户层实现
很明显Linux是属于用户级线程

用户级执行流(用户级线程) :内核lwp = 1 : 1
也有1:n的但我们今天不管了

下面来谈谈线程库中的栈
在这里插入图片描述

这个栈不仅仅要简单的变量定义,入栈出战
每个执行流本质都是一条调用链
栈结构本质是为了支持应用层完成整个函数调用链所对应的
临时变量空间的开辟和释放
所以主线程当然要有自己的调用链
新线程在执行流上和主线程是独立的,所以他们形成调用链时
必定每一个人都要有自己独立的栈结构,让自己的调用链不受别人的
干扰,所以每一个线程都要有自己的栈结构。

站在线程角度每个线程都有自己独立的栈结构,但并不是说我
想访问你这个栈我就访问不了,其实有办法


创建多线程

把pthread_create套进循环里,每次形参的tid用vector来管理起来
也方便后续等待
在这里插入图片描述
创建线程给线程入口函数传参时,可不可以传入for循环中的临时变量?
在这里插入图片描述
肯定是不可以的,for循环结束 td变量也就释放了,你传的是临时变量的地址,你不能让线程指向主线程的栈而且还是一个临时变量,传参很大可能会翻车。

用全局变量传参呢?可能就不只需要定义一个因为是多线程

我们直接new出来一个数据对象给线程传参,这是比较原始的方法。
在这里插入图片描述
td变量指向的内容是堆空间的,每一次for循环都会重新创建堆空间
所以每个线程都可以访问属于自己的堆空间。

(也可以用容器,容器的本质不也是在堆上开辟吗,那套的层就多了,麻烦。)

从这个例子可以看出,所以线程一定是共享堆空间的,要不然我随便传给你一个堆空间上的对象怎么能传给你?
说明堆空间其实被大家线程共享,只不过我们一人一个罢了
我们不要互相干扰,如果今天我就是想让线程1访问线程2 的堆空间
能做到吗?绝对可以
我们把所有堆空间指针放到一个数组里保存起来,我不就可以访问了。
但我们不这么做。
我们一个线程拿着属于自己的一个指针就走了

进程内的每个线程本来就是一家人资源互相访问很正常。


在这里插入图片描述

所有的线程,执行的都是threadRoutine这个函数,这个函数就是被重入了。

问题:每个线程都要形成test_i这个临时变量,那每个线程都执行同一个函数那这个临时变量互相会影响吗?

在这里插入图片描述
图中看到每一个线程的test_i地址都不一样
验证出了每一个线程都会有自己独立的栈结构!

问题:如果我主线程就是想访问第一个线程的test_i这个变量,在技术上能做到吗?

答案是可以的,因为新线程栈区在库里,依旧在地址空间里面
如果主线程想访问任意线程栈区数据依旧能访问
验证一下
可以利用全局定义的变量,和线程内线程名配合拿到某个线程的test_i地址,这样主线程就可以通过这个全局变量拿到了
在这里插入图片描述

其实想说的就是
其实线程和线程之间,几乎没有秘密
线程的栈上的数据,也是可以被其他线程看到并访问的。
虽然能访问甚至是修改都是可以的,但我们禁止这么做,无论堆区还是栈区每个线程只有自己知道它的虚拟地址,每个线程把自己的资源保护好,不要让别人随随便便拿走就可以了

所以每个线程都有自己独立的栈结构,但不敢说私有的栈结构


如果定义一个全局变量,然后让所有线程去访问它并且++,
那这个代码有问题吗?
在这里插入图片描述

是有问题的。
这个全局变量g_val 被多个线程共享访问,这个g_val叫共享资源
共享资源被多线程并发访问就有可能导致数据不一致问题
这个问题稍后讨论

把问题聚到一下

线程的局部存储

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

在这里插入图片描述

利用编译选项 __thread来定义,这个编译选项不是c/c++提供的,而是编译器提供的一个编译选项
它只能定义内置类型,不能用来修饰自定义类型

被它修饰的全局变量是储存在 库里面tcb线程控制块中的局部存储中。
在这里插入图片描述

这样每个线程都有自己私有的全局变量,而且每个线程的这个全局变量都是一个变量名

那这个私有全局变量有啥用?
1.例如定义变量存储pid,而不用频繁调用系统调用getpid
2.在深度调用链函数调用时,,不用把局部定义的变量传入深度函数之中,而是可以直接用这个私有全局变量。

分离线程

在这里插入图片描述

默认新创建的线程是joinable 需要被等待的 属性
如果不Join就会内存泄漏,因为它的资源不会释放

如果今天根本不关心线程把任务完成的如何,还要让主线程能腾出手不必等待了,就用pthread_detach 分离
pthread_detach 分离后
1 . 如果一个线程已经被分离了,我们不能join了,也不需要Join了
,如果join就会返回错误码,等待失败
2. == 线程执行完毕后==,原生线程库会自动释放线程
在库里把库创建的tcb,栈,底层的轻量级进程就是pcb,全都释放掉
剩下的页表,地址空间,代码数据你别管,这是人家进程的。

这个分离的工作应该由谁来做呢?
既可以由主线程来做,也可由每个线程自己来分离
在这里插入图片描述

注意是线程执行完毕以后释放线程资源,而不是调用就释放

新线程中分离时,中间这个sleep如果不加,如果新线程还没分离主线程就开始等待,那么
会偶发看到等待成功的现象

细节

分离后线程本来是能执行个5秒,但是为什么代码只输出了这么一点?
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

因为线程创建出来分离后,主线程立马开始join,分离后不能等待了,所以join直接出错立马返回,main函数也就跑完了所以进程也就结束了线程也没要结束。也就是主线程先退了

所以代码一定要保证主线程是最后退出,常见的是主线程永远不退出。

分离本质就是改线程是否是分离的属性
分离后线程依旧共享地址空间的资源,但是线程退出了和主线程没关系了

线程互斥

上面的话题 说过 定义一个全局变量,每个线程都能看到并修改这个变量,在默认情况下把这个全局变量叫做共享资源。
问题:
共享资源在被多线程并发访问时,有没有可能一个线程正在访问另一个线程就来读或者来写,进而因为另一个线程的读写修改会影响到我呢?
就会造成因为共享造成的数据不一致问题。

写一份代码,说一个场景,引入互斥的必要性

用多线程,模拟一轮抢票

有1000个座,就得卖1000张票,而不能卖出1001张

说白了就是一堆线程对全局变量做减减

肯定是票数大于0再去抢票减减,否则就是抢票完成线程退出
抢票是要花时间的,用usleep来充当时间花费
还要用Printf输出哪个线程抢到了哪个票

在这里插入图片描述
创建4个线程并发去访问同一个全局变量票数,大家都要对这个票数做减减
tickets就叫共享资源

在这里插入图片描述
最终发现抢票时竟然抢到了0,甚至-1,-2

为什么会出现这样的问题?
共享资源被多线程并发访问造成了数据不一致问题
造成这种问题肯定和多线程并发访问是有关系的
tickets- - 和判断 tickets > 0
无非每个线程执行代码时都要对变量做检测,做减减
有没有可能你正在做判断时,其他线程也来了
有没有可能你正在做tickets - - 时,其他线程也来了
多个线程都在并发访问,互相没有约束,你对ticktes做操作时,别人
也来访问了,就可能会造成数据不一致问题

我们先谈tickets - - 这个操作在多线程访问时是否是安全的问题
也就是对一个全局变量进行多线程并发 - - / ++操作是否是安全的

再来谈为什么票数会减到 - 2,虽然这两个关系不是直接相关,但是理解上面的问题,
这个现象也就能理解了。

并发访问全局变量++ – 肯定不安全

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

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

相关文章

#define宏定义

#define 语法规定 #define定义标识符 语法: #define name stuff #define例子 #include<stdio.h> #define A 100 #define STR "abc" #define FOR for(;;)int main() {printf("%d\n", A);printf("%s\n", STR);FOR;return 0; } 运行结果…

Flutter实现自定义二级列表

在Flutter开发中&#xff0c;其实系统已经给我们提供了一个可靠的二级列表展开的API&#xff08;ExpansionPanelList&#xff09;&#xff0c;我们先看系统的二级列表展开效果&#xff0c;一次只能展开一个&#xff0c;用ExpansionPanelList.radio实现 由此可见&#xff0c;已经…

5V低压步进电机驱动芯片GC6150,应用于摄像机,机器人 医疗器械等产品中。具有低噪声、低振动的特点

GC6150是双通道5V低压步进电机驱动器&#xff0c;具有低噪声、低振动的特点&#xff0c;特别适用于相机变焦对焦系统、万向架、摇头机等精度、低噪声STM控制系统&#xff0c;该芯片为每个通道集成了一个256微步的驱动器。通过SPI & T2C接口&#xff0c;客户可以方使地调整驱…

智慧机房与3D机房动环监控系统的应用

智慧机房是什么&#xff1f; 智慧机房是集采集信息、实时监控、数据分析、统一管理、故障告警等功能于一体的全方位、立体化的智能环境监控系统&#xff0c;构建物联网、大数据和云计算背景下现代企业的“数据心脏”。它能为机房管理者呈现细致入微的关键性数据&#xff0c;优…

20231211解压缩tar.xz压缩包

20231211解压缩tar.xz压缩包 缘起&#xff1a;解压缩友善之臂的NanoPC-T4(RK3399)开发板的Android11的SDK。 rootrootrootroot-X99-Turbo:~$ rootrootrootroot-X99-Turbo:~$ rootrootrootroot-X99-Turbo:~$ cd nanopc-t4/ rootrootrootroot-X99-Turbo:~/nanopc-t4$ ll total…

树根研习社|数据为王,洞察“工业数据采集”背后的价值与实践

一、工业数据采集是什么&#xff1f; 数据采集是将各种信息传感设备通过网络结合起来&#xff0c;实现任何时间、任何地点&#xff0c;人、机、物的互联互通。数据采集的主要的作用是&#xff1a; “翻译官”&#xff1a;不同程序语言的设备数据通过协议解析“翻译”为上层系…

2023年国赛高教杯数学建模A题定日镜场的优化设计解题全过程文档及程序

2023年国赛高教杯数学建模 A题 定日镜场的优化设计 原题再现 构建以新能源为主体的新型电力系统&#xff0c;是我国实现“碳达峰”“碳中和”目标的一项重要措施。塔式太阳能光热发电是一种低碳环保的新型清洁能源技术[1]。   定日镜是塔式太阳能光热发电站&#xff08;以下…

树莓派,opencv,Picamera2利用舵机云台追踪特定颜色对象

一、需要准备的硬件 Raspiberry 4b两个SG90 180度舵机&#xff08;注意舵机的角度&#xff0c;最好是180度且带限位的&#xff0c;切勿选360度舵机&#xff09;二自由度舵机云台&#xff08;如下图&#xff09;Raspiberry CSI 摄像头 组装后的效果&#xff1a; 二、项目目标…

【C语言程序设计】顺序结构程序设计

目录 前言 一、程序阅读 二、程序改错 三、程序设计 &#x1f308;嗨&#xff01;我是Filotimo__&#x1f308;。很高兴与大家相识&#xff0c;希望我的博客能对你有所帮助。 &#x1f4a1;本文由Filotimo__✍️原创&#xff0c;首发于CSDN&#x1f4da;。 &#x1f4e3;如需转…

Go语言学习:第1天

一、为什么开始学go语言 我自己是做测试的&#xff0c;所测试项目使用的是go语言。开始学习go语言的原因有两个&#xff1a;一方面&#xff0c;为了更好的做好工作&#xff1b; 另一方面&#xff0c;为了提高自己的核心竞争力。 二、第1天学习到的内容 2.1 Go是怎么解决包依…

云计算 云原生

一、引言 云计算需要终端把信息上传到服务器&#xff0c;服务器处理后再返回给终端。在之前人手一台手机的情况下&#xff0c;云计算还是能handle得过来的。但是随着物联网的发展&#xff0c;什么东西都要联网&#xff0c;那数据可就多了去了&#xff0c;服务器处理不过来&…

php实现个性化域名(短网址)和个性化登录模版的解决方案

在PHP中&#xff0c;个性化域名通常指的是根据用户或业务需求动态生成具有特定规律的子域名。实现个性化域名的方法主要依赖于服务器配置和路由规则。下面是一些基本的步骤和考虑因素&#xff0c;以帮助你了解如何个性化域名&#xff0c;并了解这样做的好处。 如何实现个性化域…

不同路径dp问题

1.状态表示 2.状态转移方程 3.初始化 4.填表顺序 从上往下填写每一行 每一行从左往右 5.返回值 dp[m][n] ------------------------------------------------------------------------------------------------------------------------------ 1.状态表示 2.状态转移方程 3…

Datawhale聪明办法学Python(task0环境配置及工具的安装)

一、课程基本结构 二、task0环境配置及工具的安装 本次测试环境为win7 Miniconda安装地址选择适合自己的Miniconda版本并安装。 本机选择Miniconda3-py37_4.12.0-Windows-x86 原因为原环境Anaconda系统环境与miniconda默认配置勾选的配置重叠&#xff1a; 重新全部卸载Anac…

基于单片机智能浇花控制系统设计

**单片机设计介绍&#xff0c;基于单片机智能浇花控制系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的智能浇花控制系统可以通过水泵、传感器和单片机等硬件组件实现自动浇水&#xff0c;减轻人工浇花的工作…

Connection refused: no further information

解决目录 一、报错信息二、解决方法 一、报错信息 二、解决方法 1、报错原因是开启了代理&#xff0c;像AS是绝对不能开代理的。 2、设置为No proxy&#xff0c;然后Apply再选择OK&#xff0c;重新同步。 要远离消耗你的人和事&#xff0c;不要花费任何情绪或者精力在他们身…

2024年江苏省职业院校技能大赛信息安全管理与评估 第三阶段教师组(样卷)

2024年江苏省职业院校技能大赛信息安全管理与评估 第三阶段教师组&#xff08;样卷&#xff09; 竞赛项目赛题 本文件为信息安全管理与评估项目竞赛-第三阶段教师组样题&#xff0c; 内容包括&#xff1a;网络安全渗透、理论技能与职业素养。 本次比赛时间为180分钟。 介绍 Ge…

如何利用Guava优化Java网络编程

第1章&#xff1a;引言 大家好&#xff01;今天小黑要和咱们聊聊一个很酷的话题&#xff1a;如何利用Google的Guava库来优化Java网络编程。网络编程&#xff0c;这玩意儿听起来就高大上&#xff0c;不是吗&#xff1f;但实际上&#xff0c;它充满了各种挑战。从处理复杂的数据…

7 Linux 内核移植

一、编译 ST 的 Linux 系统 1. 压缩源码 首先先下载 ST 官方源码&#xff0c;之前章节已经下载过了&#xff0c;直接输入以下命令&#xff1a; cd linux/atk-mpl/stm32mp1-openstlinux-5.4-dunfell-mp1-20-06-24/sources/arm-ostl-linux-gnueabi/linux-stm32mp-5.4.31-r0/ 然…

SiteGround如何设置WordPress网站自动更新

SiteGround Autoupdate功能会自动帮我们更新在他们这里托管的所有WordPress网站&#xff0c;这样做是为了保证网站安全&#xff0c;并且让它们一直保持最新状态。他们会根据我们选择的设置自动更新不同版本的WordPress&#xff0c;包括主要版本和次要版本。在每次自动更新之前&…