详解互斥信号量的概念和运行
https://blog.csdn.net/weichushun/article/details/122744773
互斥信号量的主要作用是对资源实现互斥访问,使用二值信号量也可以实现互斥访问的功能,不过互斥信号量与二值信号量有区别。
===========================
理解互斥量和信号量
互斥量(Mutex)
互斥量表现互斥现象的数据结构,也被当作二元信号灯。
一个互斥基本上是一个多任务敏感的二元信号,它能用作同步多任务的行为,它常用作保护从中断来的临界段代码并且在共享同步使用的资源。
死锁主要发生在有多个依赖锁存在时, 会在一个线程试图以与另一个线程相反顺序锁住互斥量时发生. 如何避免死锁是使用互斥量应该格外注意的东西。
总体来讲, 有几个不成文的基本原则:
对共享资源操作前一定要获得锁。
完成操作以后一定要释放锁。
尽量短时间地占用锁。
如果有多锁, 如获得顺序是ABC连环扣, 释放顺序也应该是ABC。
线程错误返回时应该释放它所获得的锁。
Mutex可以被抽象为四个操作:
- 创建 Create
- 加锁 Lock
- 解锁 Unlock
- 销毁 Destroy
信号量
信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施, 它负责协调各个线程, 以保证它们能够正确、合理的使用公共资源。
Semaphore可以被抽象为五个操作:
- 创建 Create
- 等待 Wait:
-释放 Post
-试图等待 TryWait
-销毁 Destroy
===========================
关于互斥信号量和二值信号量的区别
二值信号量:
用于任务同步和中断同步,也可以实现互斥访问,但不具有优先级继承
通过二值信号量实现互斥访问:
1.创建3个任务task1,task2,task3,优先级分别是 3,2,1(高--->低).
2. 开始task3首先获得二值信号量资源,但task1优先级比task3高抢占了task3的cpu使用权
3. task1也需要获取二值信号量,所以task1就会挂起,等待task3释放二值信号量。
4. 由于 task2已经处于就绪态,并且优先级比task3高,task2抢占了task3的cpu使用权,此时优先级翻转就发生了,task1(高优先任务)需要等待task2(低优先任务)运行完后才能运行,task3任务继续执行并释二值信号量资源,task1才能获取到二值信号量,从而可以继续执行
互斥信号量:
互斥信号量简单说是具有优先级继承的二值信号量,用于进程中的互斥,不可用于中断中(1:具有优先级继承机制,2:中断服务函数不能因为等待互斥信号量而阻塞)
互斥信号量优先级继承机制:
当一个低优先级的任务正在使用这个互斥信号量时,高优先的任务在等待这个互斥信号量的时候,高优先级的任务会将低优先级的任务的优先级提到和自己同一个水平(目的:避免优先级翻转),从而来避免位于低优先和高优先的任务抢占cpu时间运行,而导致次优先级任务先于高优先级的任务运行,引起优先级翻转。
注:包含了2方面的内容:??
即使是最低优先级的task, 一旦对目标资源已经成功加锁,则即使是高优先级的task,也无法抢占。当然,系统级别的中断任务、或其他他别任务,还是可以抢占的。
优先级翻转,发生于都处在等待该资源的、其他多个的、任务之间。
优先级继承也只是尽可能的降低优先级翻转的发生,软件设计的时候需避免优先级翻转的问题发生
通过互斥信号量实现互斥访问:
与上一个说明相比,这是容易理解的说明:
1.一开始task3开始运行,先获取到互斥锁
2. task1开始运行尝试去获取互斥锁失败被阻塞等待task3执行完,但是此时提升task3的优先级,让其优先级跟自己一样
3.task3运行过程中,task2被触发,由于其优先级低于task3(第2步被提升过),task2等待运行
4.继续运行task3,运行完后释放互斥锁
5.task1继续运行
6.task1执行完,执行task2所以过程跟前面的虽然一样,但是互斥锁多做了一个步骤就是将task3的优先级提升到task1的级别,防止task2中途出来搅局浪费大量时间
链接:https://www.jianshu.com/p/6aba818784d8
FreeRTOS互斥信号量与二值信号量使用时的区别
1.互斥信号量
互斥信号量的申请与释放是要在同一个任务中进行的,不能在一个任务中申请而在另一个任务中释放。
互斥信号量主要解决的是,我在用的时候,别人都不能用。举个例子,我在像一段内存中写数据的时候,不允许别人去写和读的,这时候就需要互斥信号量,写之前获取信号量,写完之后再释放互斥信号量。
2.二值信号量
二值信号量允许在一个任务中申请,在另外一个任务中释放。
二值信号量主要解决的是任务同步的问题。举个例子,一个任务用于处理UART的数据,UART中断中接受数据,当任务处理数据时就获取信号量,中断接受到数据就释放信号量,这样就可以使得中断与任务接受和处理协同处理。
————————————————
版权声明:本文为CSDN博主「MC_J」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_37868856/article/details/105770937