Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
2024-RSOC
【2024_RSOC】线程间同步和通信
发布于 2024-07-24 21:36:24 浏览:406
订阅该版
#线程间的同步和通信 ##线程间的同步: ###什么是线程间的同步? 一项工作的完成往往可以通过多个线程协调的方式共同来完成,那么多个线程之间 “默契” 的协作完成任务就是线程间的同步。 ###为什么需要线程间的同步? 举个例子,一项工作中的两个线程:一个线程从传感器中接收数据并且将数据写到共享内存中,同时另一个线程周期性的从共享内存中读取数据并发送去显示,如果对共享内存的访问不是排他性的,那么各个线程间可能同时访问它,这将引起数据一致性的问题:在显示线程试图显示数据之前,接收线程还未完成数据的写入,那么显示将包含不同时间采样的数据,造成显示数据的错乱。 ![1.png](https://oss-club.rt-thread.org/uploads/20240724/1bac804cbbd38b776e222ea05c00260f.png) ###既然知道了线程同步的原因,那么同步的方式有几种呢? **1,信号量**: 以生活中的停车场为例来理解信号量的概念: ①当停车场空的时候,停车场的管理员发现有很多空车位,此时会让外面的车陆续进入停车场获得停车位; ②当停车场的车位满的时候,管理员发现已经没有空车位,将禁止外面的车进入停车场,车辆在外排队等候; ③当停车场内有车离开时,管理员发现有空的车位让出,允许外面的车进入停车场;待空车位填满后,又禁止外部车辆进入。 在此例子中,管理员就相当于信号量,管理员手中空车位的个数就是信号量的值(非负数,动态变化);停车位相当于公共资源(临界区),车辆相当于线程。车辆通过获得管理员的允许取得停车位,就类似于线程通过获得信号量访问公共资源。 ![06sem_work.png](https://oss-club.rt-thread.org/uploads/20240724/cd5fdfc2d62eef2c92fccb90961bf21a.png) **获取信号量**:创建好信号量之后,线程可以发送和接收信号量,并且可以设置等待时间。当信号量值大于零时,线程可以获得信号量,并且相应的信号量值会减1,如果信号量的值等于零,那么说明当前信号量资源实例不可用,申请该信号量的线程将根据 time 参数的情况选择直接返回、或挂起等待一段时间、或永久等待,直到其他线程或中断释放该信号量。 **释放信号量**:当信号量的值等于零时,并且有线程等待这个信号量时,释放信号量将唤醒等待在该信号量线程队列中的第一个线程,由它获取信号量;否则将把信号量的值加1。 **删除信号量**:如果删除该信号量时,有线程正在等待该信号量,那么删除操作会先唤醒等待在该信号量上的线程(等待线程的返回值是 - RT_ERROR),然后再释放信号量的内存资源。下表描述了该函数的输入参数与返回值。 疑问: 1.当一个持有信号量的线程再次获取信号量且信号量值大于0时,信号量值是否还会减1?如果信号量值等于0且等待时间为永久那么该线程是否会卡死? 2.如果持续释放信号量且无其他线程获取是否会一直增加信号量值? **总结**:信号量就像一个篮子里面装的一次性物品,使用时就获取信号量,然后篮子里的物品少一个。当篮子里的物品没有了就释放信号量,然后增加一个物品供其他线程使用。 **2,互斥量**: 互斥量又叫相互排斥的信号量,是一种特殊的二值信号量。互斥量类似于只有一个车位的停车场:当有一辆车进入的时候,将停车场大门锁住,其他车辆在外面等候。当里面的车出来时,将停车场大门打开,下一辆车才可以进入。 与信号量的区别: ①持有该互斥量的线程也能够再次获得这个锁而不被挂起。 ②防止优先级翻转 ③互斥量只能由持有线程释放。 **注意:互斥量的 flag 标志已经作废,无论用户选择 RT_IPC_FLAG_PRIO 还是 RT_IPC_FLAG_FIFO,内核均按照 RT_IPC_FLAG_PRIO 处理。** **获取互斥量**:如果互斥量没有被其他线程控制,那么申请该互斥量的线程将成功获得该互斥量。**如果互斥量已经被当前线程线程控制,则该互斥量的持有计数加1**,当前线程也不会挂起等待。如果互斥量已经被其他线程占有,则当前线程在该互斥量上挂起等待,直到其他线程释放它或者等待时间超过指定的超时时间。 ![](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/ipc1/figures/06mutex_work.png) **释放互斥量**:**只有已经拥有互斥量控制权的线程才能释放它**,每释放一次该互斥量,它的持有计数就减 1。当该互斥量的持有**计数为零时(即持有线程已经释放所有的持有操作),它变为可用**,等待在该互斥量上的线程将被唤醒。如果线程的运行优先级被互斥量提升,那么当互斥量被释放后,线程恢复为持有互斥量前的优先级。(持有线程如果多次获取,那么要想让出资源就需要多次释放) **删除互斥量**:当删除一个互斥量时,所有等待此互斥量的线程都将被唤醒,等待线程获得的返回值是 - RT_ERROR。然后系统将该互斥量从内核对象管理器链表中删除并释放互斥量占用的内存空间。 **总结**:互斥量就像一本唯一的书,每次使用就需要获取一次互斥量,如果没被人使用就拿走,如果被人拿走就需要排队了。而正在使用的人想让出使用权就释放相应次数的互斥量。 **3,事件集**: 一个事件集可以包含多个事件,利用事件集可以完成一对多,多对多的线程间同步。与信号量不同,它的特点是可以实现一对多,多对多的同步。即一个线程与多个事件的关系可设置为:其中任意一个事件唤醒线程,或几个事件都到达后才唤醒线程进行后续的处理;同样,事件也可以是多个线程同步多个事件。这种多个事件的集合可以用一个 32 位无符号整型变量来表示,变量的每一位代表一个事件 ![事件.png](https://oss-club.rt-thread.org/uploads/20240724/a599071aebedd356b77f7e3e19d0d1fc.png) RT-Thread 定义的事件集有以下特点: 1)事件只与线程相关,事件间相互独立:每个线程可拥有 32 个事件标志,采用一个 32 bit 无符号整型数进行记录,每一个 bit 代表一个事件; 2)事件仅用于同步,不提供数据传输功能; 3)***事件无排队性,即多次向线程发送同一事件 (如果线程还未来得及读走),其效果等同于只发送一次。** **发送事件**: 通过参数 set 指定的事件标志来设定 event 事件集对象的事件标志值,然后遍历等待在 event 事件集对象上的等待线程链表,判断是否有线程的事件激活要求与当前 event 对象事件标志值匹配,如果有,则唤醒该线程。 其本质就是把不同事件(不同的标志位)和在一起形成事件集,然后把时间集发送出去。发送之后事件集会与**当前**接收该事件集的线程进行标志位比较,符合要求就唤醒线程。 **接收事件**: 系统首先根据 set 参数和接收选项 option 来判断它要接收的事件是否发生,如果已经发生,则根据参数 option 上是否设置有 RT_EVENT_FLAG_CLEAR *来决定是否重置**当前**所接收的事件的相应标志位*,然后返回(其中 recved 参数返回接收到的事件);如果没有发生,则把等待的 set 和 option 参数填入线程本身的结构中,然后把线程挂起在此事件上,直到其等待的事件满足条件或等待时间超过指定的超时时间。 其实就是一直判断某一事件集中的某些二进制位是否置1,直到符合要求的标志位置1或超时或一直判断。 **删除事件集**: 删除一个事件集对象时,应该确保该事件集不再被使用。在删除前会唤醒所有挂起在该事件集上的线程(线程的返回值是 - RT_ERROR),然后释放事件集对象占用的内存块。 **总结**:事件集就像一个服务员,客人(线程)将自己需要的菜(事件标志位)写在菜单上(接收事件),厨师做好菜后拿给服务员(发送事件),服务员根据菜单上的要求对比各个客人需要的菜(遍历标志位),如果满足要求就给客人(唤醒线程),没有就直到其等待的事件满足条件或等待时间超过指定的超时时间。 ##线程间的通信:
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
马桶盖盖子
这家伙很懒,什么也没写!
文章
7
回答
0
被采纳
0
关注TA
发私信
相关文章
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
ulog
C++_cpp
at_device
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
a1012112796
13
个答案
2
次被采纳
张世争
9
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
本月文章贡献
程序员阿伟
9
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
5
次点赞
RTT_逍遥
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部