当前位置: 首页 > news >正文

线程--线程同步

这里写目录标题

  • 同步概念
    • 线程同步概念
    • 数据混乱原因
  • 互斥量
    • 原理
    • 锁的注意事项
      • 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、在每个线程访问共享区的前后进行加锁和解锁:
子线程:
在这里插入图片描述
主线程:
在这里插入图片描述

效果:
在这里插入图片描述每个线程的数据被完整的加入到了共享区

注意事项

假如说,我们把解锁的操作移到循环步的最后:
在这里插入图片描述
在这里插入图片描述
可以看到,主线程和子线程都使用加锁和解锁把原来的所有代码包裹起来,这样结构上确实很清晰

但是:
在这里插入图片描述
在这里插入图片描述
可以看到,最终要么只执行主线程,要么只执行子线程

原因:
由于线程在解锁之后立马就进入下一个循环,使得解锁之后该线程又拿到了锁,所以,就会一直保持一个线程,另一个线程无法拿到锁

所以:
在这里插入图片描述
我们的加锁和解锁操作,只在访问共享区的前后,立即执行,锁尽量只包含访问共享区的代码部分

补充:
在这里插入图片描述
可以将互斥锁的操作看成整数,
初始化时,值为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

在这里插入图片描述

条件变量

二级目录

二级目录

二级目录

信号量

二级目录

二级目录

二级目录

一级目录

二级目录

二级目录

二级目录


http://www.mrgr.cn/news/25994.html

相关文章:

  • 怎么看待伦敦银交易的风险与收益?
  • @Data、@NoArgsConstructor和@AllArgsConstructor这三个Lombok注解的含义
  • FunASR 部署
  • postcss-pxtorem实现页面自适应
  • SpringDoc介绍
  • 品牌借势华为三折叠手机上市热点文案
  • 初学51单片机之IO口上下拉电阻相关
  • [产品管理-12]:NPDP新产品开发 - 10 - 组合管理 - 新产品机会的选择
  • ASPP模块笔记
  • 中伟视界:皮带跑偏检测算法及其实现模型和判断方法
  • Segger Embedded Studio 的使用
  • 通过python提取PDF文件指定页的图片
  • 罗马数字与整数(水)
  • 深度神经网络
  • 已经30岁了,想转行从头开始现实吗?什么样的工作算好工作?
  • Vue - 详细介绍vue-qr在线生成二维码组件(Vue2 Vue3)
  • Jetson 部署 Faster Whisper
  • 有什么软件可以规范员工上班玩游戏?
  • 【F的领地】项目拆解:百家号批量搬运掘金 | 搬运类项目核心思路分享
  • shell脚本中sed命令如何使用变量