线程--线程同步
这里写目录标题
- 同步概念
- 线程同步概念
- 数据混乱原因
- 互斥量
- 原理
- 锁的注意事项
- 1、cpu时间轮片
- 2、建议锁
- 总结
- 使用锁来管理线程同步
- 问题产生
- 主要函数
- init、destory
- lock、unlock
- 代码
- 注意事项(锁的粒度)
- try锁
- 死锁
- 出现原因
- 图解
- 读写锁
- 特性
- 图解
- 函数
- 总览
- init、destroy
- rdlock、tryrdlock
- wrlock、trywrlock
- unlock
- 代码
- 条件变量
- 二级目录
- 二级目录
- 二级目录
- 信号量
- 二级目录
- 二级目录
- 二级目录
同步概念
线程同步概念

数据混乱原因

互斥量
原理

多个线程操作共享区时,每个线程访问时,会加上一把锁,只允许某单个线程对共享区进行操作,操作完之后,再解锁,表示允许其他线程访问
而这个锁就叫互斥锁,这个互斥锁只有一把,各个线程争抢这把锁,谁先拿到锁,谁先有操作共享区的权利
锁的注意事项
1、cpu时间轮片

当线程T1执行写入0的操作的过程中,T1的cpu时间到了,那么就会让出cpu,之后给到T2,但是由于此时共享区还在被锁的状态,所以T2只好阻塞在锁上,等待锁的解锁,之后,过段时间,就会又让出cpu给到T3,T3此时也会阻塞在锁上,然后过段时间,再次让出cpu给T1,T1此时拿着锁,可以操作共享区,所有会继续上次中断的地方继续操作共享区
2、建议锁

假如说,当T3拿到cpu时间之后,并不阻塞在锁上,而是就要强制访问共享区,那么也是可以的,只不过会造成数据混乱而已,所以,互斥锁并不是一个强制的概念,而是一个建议,他的强制性体现在代码逻辑上,而不是底层系统的强制操作,如果T3的代码逻辑中使用了锁,那么T3就无法访问共享区,当然T3也可以不使用锁,直接访问,代码层面也是可以运行的
总结

使用锁来管理线程同步
问题产生

使用两个线程,同时向“公共输出”(共享区)写数据,没有加锁机制
效果:
打印完全随机,各个线程的一帧数据写入都会被其他线程打断、插入其他数据

主要函数

其中,trylock函数,表示会让当前线程尝试加锁,看看能不能加上,加不上了先去做自己的事,过段时间再来尝试,而不是像之前说的“阻塞在锁上”
而五个函数的下面是一个变量,这个变量就是互斥量,就是锁本身,他只有0、1两种取值
大概流程:

init、destory

对于init:
参数一:传入互斥锁的地址,
参数二:互斥锁的属性,如果想使用默认属性,那么就传NULL
其中,对于restrict关键字:
他是用来修饰指针的,

可以说,这个内存就认定了这个指针,注意与指针认定内存有区别(顶层const)
对于顶层const,是站在指针的角度,对于一个指针来说,他只存储某块内存的地址,但是该地址还可以被其他指针所存储和操作
而对于restrict,是站在内存的角度,对于一块内存的操作来说,他只认定那个指针,其他指针无法操作该内存
返回值:成功:0。失败:返回error number
lock、unlock

代码
1、创建互斥锁(全局变量)

2、在主线程创建子线程之前,要将锁初始化完毕

并在最后所有线程结束后销毁互斥锁:

3、在每个线程访问共享区的前后进行加锁和解锁:
子线程:

主线程:

效果:
每个线程的数据被完整的加入到了共享区
注意事项(锁的粒度)
假如说,我们把解锁的操作移到循环步的最后:


可以看到,主线程和子线程都使用加锁和解锁把原来的所有代码包裹起来,这样结构上确实很清晰
但是:


可以看到,最终要么只执行主线程,要么只执行子线程
原因:
由于线程在解锁之后立马就进入下一个循环,使得解锁之后该线程又拿到了锁,所以,就会一直保持一个线程,另一个线程无法拿到锁
所以:

我们的加锁和解锁操作,只在访问共享区的前后,立即执行,锁尽量只包含访问共享区的代码部分
最好在解锁之后,加个sleep
补充:

可以将互斥锁的操作看成整数,
初始化时,值为1,表示当前锁可以被拿取并使用
之后,加锁时,–,那么值变为0,表示已经加锁,锁目前被占用,无法使用,其他线程就无法使用锁,无法访问共享区了
最后,解锁时,++,值变回1,表示再次可以使用
try锁

注意,他有一个点:即加锁失败会直接返回错误号,并且不阻塞
lock如果加锁失败,是会阻塞在锁上等待锁的释放的
死锁
出现原因

图解

对于第一种情况:
反复加锁:
当一个线程去拿某个共享区的锁时,已经拿到了,之后,这个线程再次去lock
那么此时由于第一次这个锁已经被lock了。所以,第二次的lock会失败然后阻塞在锁上等待锁的释放,而能释放锁的线程就是当前阻塞的这个线程,所以,也就导致线程永远无法继续执行了,所以造成死锁
对于第二种情况:
如果有两个共享区,那么每个共享区都有一个锁,如果有一种场景:一个线程必须要拿到两个锁,才能继续向下执行自己的业务
此时,线程1拿到A锁,之后他想去拿B锁,但是,被线程2抢先一步拿到B锁,此时,线程1lock会失败并且阻塞在B锁,而线程2拿到B锁之后去拿A锁,由于A锁被线程1拿到了,所以线程2也会阻塞在A锁,这样,两个线程都在阻塞,且阻塞在一个“正处于阻塞”的线程所掌握的锁上,也就都无法继续向下执行了,造成死锁
读写锁
特性

读锁可以共享,写锁与上面的互斥锁是一样的

图解
1、当所有的锁都是读锁:

遵循读共享的原则,那么此时四个锁都可以加锁成功,共同去读数据
2、假如说两个线程(一个是读、一个是写)同时来加锁:

假如某一时刻,线程1来加读锁,线程2加写锁,那么会优先让写锁加锁成功,注意,此时指的是某一刻,两个线程,同时加锁,这种情况很少出现
3、已经有两个读线程加了读锁,此时来了两个写线程,想要加写锁:

如果已经有两个读线程加了读锁,此时来了两个写线程,想要加写锁,那么注意,上面说的写锁的优先级高,是在r、w锁同时来请求加锁的时刻才会去考虑,现在r以及加上了锁,那么w锁就必须阻塞等待锁被释放,并且是所有的r线程都释放完毕,w锁才能加上
但是,此时有两把w锁,写锁是不会共享的,所以只能有一个线程加上w锁,这个就要争抢了,一旦一个加上了w锁,另一个w线程就要继续阻塞等待,这就是“写独占”
4、线程1已经加上了r锁,此时,同时来了两个w锁和一个r锁:

线程1已经加上了r锁,此时,同时来了两个w锁和一个r锁,这个时候,r锁是不能直接加锁的,虽然读锁共享,但是要先遵循“写锁优先”。对于同时来的情况,只有w锁处理完了。才会去处理r锁,所以,此时T3会等待T2、T4加锁解锁之后,才能去加锁,T2、T4也要先等待T1把锁释放了才能去加锁
函数
总览

其中,初始化锁、销毁锁、解锁操作都是一个(解锁是一个,是因为只有一个锁,不管指定是读锁还是写锁,都是同一把锁)
而加锁、和try锁,都是两个,因为这里涉及到是指定写锁还是读锁
init、destroy

rdlock、tryrdlock

wrlock、trywrlock

unlock

代码



效果:

可以看到,read线程占比较多,这也是读写锁的优势,r更多
条件变量
二级目录
二级目录
二级目录
信号量
二级目录
二级目录
二级目录
相关文章:
线程--线程同步
这里写目录标题 同步概念线程同步概念数据混乱原因 互斥量原理锁的注意事项1、cpu时间轮片2、建议锁总结 使用锁来管理线程同步问题产生主要函数init、destorylock、unlock代码注意事项(锁的粒度) try锁死锁出现原因图解 读写锁特性图解函数总览init、de…...
【QT】Qt窗口
欢迎来到Cefler的博客😁 🕌博客主页:折纸花满衣 🏠个人专栏:QT 目录 👉🏻菜单栏设置👉🏻QToolBar练习 👉🏻QStausBar👉🏻Q…...
场外个股期权怎么给股票加杠杆?
今天期权懂带你了解场外个股期权怎么给股票加杠杆?场外期权交易通过向证券公司支付一定额度的股票期权费,然后买入大额的股票持仓,从而实现的杠杆交易。 买入看涨期权 操作:支付权利金购买看涨期权。 杠杆作用: 期…...
【Docker部署ELK】(7.15)
1、拉取镜像 docker pull docker.elastic.co/elasticsearch/elasticsearch:7.15.0 docker pull docker.elastic.co/kibana/kibana:7.15.0 docker pull docker.elastic.co/logstash/logstash:7.15.02、配置文件(解压资源到D盘DOCKER目录下) 2.1 配置文件…...
UE4_后期处理_后期处理材质及后期处理体积一
后期处理效果 在渲染之前应用于整个渲染场景的效果。 后期处理效果(Post-processing effect)使美术师和设计师能够对影响颜色、色调映射、光照的属性和功能进行组合选择,从而定义场景的整体外观。要访问这些功能,可以将一种称为…...
【PyQt6 应用程序】基于QtDesigner做一个用户登录页面
在当今的软件开发领域,用户界面(UI)设计和后端编程是创建现代、互动应用程序的两大重要组成部分。尤其是在开发具有用户登录功能的应用程序时,不仅要注重外观和用户体验的设计,还要确保后端逻辑的安全性和可靠性。 本文将介绍如何使用PyQt6框架结合UI设计,实现一个简单而…...
Ollama—87.4k star 的开源大模型服务框架!!
这一年来,AI 发展的越来越快,大模型使用的门槛也越来越低,每个人都可以在自己的本地运行大模型。今天再给大家介绍一个最厉害的开源大模型服务框架——ollama。 项目介绍 Ollama 是一个开源的大语言模型(LLM)服务工具…...
MySQL表的操作与数据类型
目录 前言 一、表的操作 1.创建一个表 2.查看表的结构 3.修改表 4.删除一个表 二、 MySQL的数据类型 0.数据类型一览: 1.整数类型 2.位类型 3.小数类型 4.字符类型 前言 在MySQL库的操作一文中介绍了有关MySQL库的操作,本节要讲解的是由库管理的结构——…...
mysql把某一个字段的值中的aa,替换成bb
UPDATE my_table SET my_column REPLACE(my_column, aa, bb); 例 假设my_table表在替换前的数据如下: idmy_column1hello aa2world aa aa3no aa here 执行上述UPDATE语句后,my_table表的数据将变为: idmy_column1hello bb2world bb b…...
【系统架构设计师】原型模式详解
原型模式详解 1. 什么是原型模式? 原型模式(Prototype Pattern)是一种创建型设计模式,它允许通过复制已有的对象来创建新的对象,而不是通过类实例化来创建新对象。通过这种方式,原型模式能够减少创建对象的开销,尤其是当对象的创建过程非常复杂或者耗费资源时。原型模…...
Spring @Async 深度解读:默认线程池执行器的配置与优化
在Spring中,Async注解用于异步执行方法。默认情况下,Async注解的任务是由一个线程池执行的。然而,这个默认的线程池是如何初始化的呢?本文将深入探讨这一过程,帮助你理解Spring异步任务背后的线程池执行器的初始化原理…...
手把手教你用护核纪元地心护核者用服务器开服联机
1、购买后登录服务器面板(百度莱卡云面板) 登录面板的信息在绿色的登陆面板按键下方,不是你的莱卡云账号 进入控制面板后会出现正在安装的界面,安装大约3分钟(如长时间处于安装中请联系我们的客服人员) 2、…...
Log4j 1.x如何升级到Log4j 2.x
Log4j 1.x升级到Log4j 2.x是一个涉及多个步骤的过程,主要包括删除旧版本、添加新版本依赖、配置新版本的配置文件等。以下是一个详细的升级步骤指南: 一、准备阶段 了解当前项目依赖: 检查项目中所有使用Log4j 1.x的地方,包括ja…...
CloudFlare问题与CDN问题
昨天将腾讯云的解析转移到Cloudflare中了,结果今天发现网站崩了,显示重定向次数过多,昨天估计是因为浏览器缓存,所以没有发现问题 问题一:强制HTTPS 当时看到CloudFlare的强制https时就想到了我的宝塔面板也开着强制h…...
[Linux]:文件(上)
✨✨ 欢迎大家来到贝蒂大讲堂✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 所属专栏:Linux学习 贝蒂的主页:Betty’s blog 1. C语言文件操作 C语言文件操作接口如下,详情可参照——C语言文…...
flutter开发多端平台应用的探索 下 (跨模块、跨语言通信之平台通道)
前文 Flutter 是一个跨平台的开发框架,它允许开发者使用相同的代码库来构建 iOS、Android、Web 和桌面应用程序。 上文flutter开发多端平台应用的探索 上(基本操作)-CSDN博客列举了一些特定平台的case(桌面端菜单,鼠…...
第15-02章:理解Class类并获取Class实例
我的后端学习大纲 我的Java学习大纲 1、Java反射机制原理图: 源代码通过Javac编译得到字节码文件,当我执行到new一个对象的时候,字节码文件会通过ClassLoader被加载,然后得到一个Class类对象,存放在堆中,加…...
【Authing身份云-注册安全分析报告-无验证方式导致安全隐患】
前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 1. 暴力破解密码,造成用户信息泄露 2. 短信盗刷的安全问题,影响业务及导致用户投诉 3. 带来经济损失,尤其是后付费客户,风险巨大,造…...
idea插件推荐之Cool Request
Cool Request是一款基于IDEA的HTTP调试工具,可以看成是轻量版的postman,它会自动扫描项目代码中所有API路径,按项目分组管理。一个类被定义为Controller且其中的方法被RequestMapping或者XXXMapping注解标注以后就会被扫描到。 对应方法左侧会…...
从卫星和飞机等不同传感器方面由QGIS 遥感分析
在地理信息科学 (GIS) 中,遥感是指从远处获取有关地球表面特征信息的行为。遥感数据是从许多不同的平台获取而来,包括卫星、飞机和具有许多不同传感器的固定仪器,包括光谱图像(相机)和激光雷达。最常见的遥感数据形式是卫星和航空图像。 为了充分实现这些照片的价值,需要…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...
[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.
ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #:…...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
Mysql故障排插与环境优化
前置知识点 最上层是一些客户端和连接服务,包含本 sock 通信和大多数jiyukehuduan/服务端工具实现的TCP/IP通信。主要完成一些简介处理、授权认证、及相关的安全方案等。在该层上引入了线程池的概念,为通过安全认证接入的客户端提供线程。同样在该层上可…...
