FreeRTOS ~(七)互斥量 ~ (3/3)互斥量的缺陷和递归锁

news2024/11/14 15:07:55

前情提要
FreeRTOS ~(四)同步互斥与通信 ~ (2/3)互斥的缺陷
FreeRTOS ~(五)队列的常规使用 ~ (2/5)队列解决互斥缺陷
FreeRTOS ~(六)信号量 ~ (2/3)信号量解决互斥缺陷
FreeRTOS ~(七)互斥量 ~ (1/3)互斥量解决互斥缺陷
FreeRTOS ~(七)互斥量 ~ (2/3)互斥量解决优先级反转问题
互斥量的缺陷

static SemaphoreHandle_t xSemUART;		/* 互斥量的句柄 */

void TaskGenericFunction(void * param)
{
	while (1)
	{
		/* 将互斥量置0,关闭串口使用权,
		   防止被Tick中断的时候,任务切换后,其他任务使用串口 */
		xSemaphoreTake(xSemUART, portMAX_DELAY);
		printf("%s\r\n", (char *)param);
		/* 将互斥量置1,激活串口使用权 */
		xSemaphoreGive(xSemUART);
		vTaskDelay(1);
	}
}

void Task5Function(void * param)
{
	/* 一进来,先Delay10ms,让其他任务先执行 */
	vTaskDelay(10);
	while (1)
	{
		while(1)
		{
			/* Task5在这里做一个破坏,
			   无论Task5有没有获得信号量,也就是有没有获得锁,就将该信号量释放掉,
			   一般来说只有当谁拥有锁的时候,就有谁去释放,这才是正确的 */
			if(xSemaphoreTake(xSemUART,0) != pdTRUE)
				xSemaphoreGive(xSemUART);
			else
				break;
		}
		printf("%s\r\n", (char *)param);
		xSemaphoreGive(xSemUART);
		vTaskDelay(1);
	}
}
/*-----------------------------------------------------------*/
int main( void )
{
	prvSetupHardware();
	xSemUART = xSemaphoreCreateMutex();
	
	xTaskCreate(TaskGenericFunction, "Task3", 100, "Task 3 is running", 1, NULL);
	xTaskCreate(TaskGenericFunction, "Task4", 100, "Task 4 is running", 1, NULL);
	xTaskCreate(Task5Function, "Task5", 100, "Task 5 is running", 1, NULL);
	
	vTaskStartScheduler();
	return 0;
}

在这里插入图片描述
解决互斥量的缺陷---引入递归锁

相较于上述的代码:
更换几个API函数即可;
xSemaphoreTake -> xSemaphoreTakeRecursive
xSemaphoreGive -> xSemaphoreGiveRecursive
xSemaphoreCreateMutex -> xSemaphoreCreateRecursiveMutex
代码如下:
static SemaphoreHandle_t xSemUART;

void TaskGenericFunction(void * param)
{
	while (1)
	{
		xSemaphoreTakeRecursive(xSemUART, portMAX_DELAY);
		printf("%s\r\n", (char *)param);
		xSemaphoreGiveRecursive(xSemUART);
		vTaskDelay(1);
	}
}

void Task5Function(void * param)
{
	vTaskDelay(10);
	while (1)
	{
		while(1)
		{
			/* Task5如果没有获得信号量,也就是Task5获得锁不成功,
			   那么释放这个锁也是不成功的 */
			if(xSemaphoreTakeRecursive(xSemUART,0) != pdTRUE)
				xSemaphoreGiveRecursive(xSemUART);
			else
				break;
		}
		printf("%s\r\n", (char *)param);
		xSemaphoreGiveRecursive(xSemUART);
		vTaskDelay(1);
	}
}
/*-----------------------------------------------------------*/
int main( void )
{
	prvSetupHardware();
	xSemUART = xSemaphoreCreateRecursiveMutex();
	xTaskCreate(TaskGenericFunction, "Task3", 100, "Task 3 is running", 1, NULL);
	xTaskCreate(TaskGenericFunction, "Task4", 100, "Task 4 is running", 1, NULL);
	xTaskCreate(Task5Function, "Task5", 100, "Task 5 is running", 1, NULL);
	vTaskStartScheduler();
	return 0;
}
/*-----------------------------------------------------------*/

在这里插入图片描述

递归锁解决的就是由谁上的锁,就必须由谁解锁.
这样就解决掉了互斥量自己上锁可能会被别人解锁的缺陷.
递归锁会记录谁是锁的拥有者,且在拥有锁的时候可以不断的执行加锁开锁这样的过程.
如下方式修改代码,就可以看到这样的过程.
void TaskGenericFunction(void * param)
{
	int i;
	while (1)
	{
		xSemaphoreTakeRecursive(xSemUART, portMAX_DELAY);
		printf("%s\r\n", (char *)param);
		/* 上面已经Take了,说明获得锁了,
		   那么就可以不断的上锁解锁 */
		for(i = 0; i < 10; i++)
		{
			xSemaphoreTakeRecursive(xSemUART, portMAX_DELAY);
			printf("%s in loop %d\r\n", (char *)param,i);
			xSemaphoreGiveRecursive(xSemUART);
		}
		/* 最后使用完就解锁 */
		xSemaphoreGiveRecursive(xSemUART);
		vTaskDelay(1);
	}
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

超详细 | 遗传-粒子群自适应优化算法及其实现(Matlab)

作者在前面的文章中介绍了两种经典的优化算法——遗传算法(GA)和粒子群算法(PSO)&#xff0c;这些智能优化算法解决问题的方式和角度各不相同&#xff0c;都有各自的适用域和局限性&#xff0c;对智能优化算法自身做的改进在算法性能方面得到了一定程度的提升&#xff0c;但算法…

前端如何实现面向对象

交流所记&#xff1a; 面向对象的三要素&#xff1a; 封装&#xff1a;把客观事物封装成抽象的类&#xff0c;并且类可以把自己的数据和方法只让可信的类或者对象操作&#xff0c;对不可信的类或者对象隐藏信息继承&#xff1a;它可以使用现有类的所有功能&#xff0c;并在无…

链上衍生品协议 ProsperEx:探索 RWA 叙事,打造 DeFi 变异黑马

“ProsperEx 本身背靠着具备潜力的链上衍生品赛道&#xff0c;同时也是 RWA 领域早期的布局者之一&#xff0c;其有望成为 Web2 世界与 Web3 世界的早期连接点&#xff0c;并具备广泛且规模性捕获用户的能力。” 从2020年DeFi之夏链上世界迎来了爆发后&#xff0c;链上衍生品赛…

SQL21 浙江大学用户题目回答情况

解法一:left JOIN select t1.device_id,question_id,result from question_practice_detail t1 left JOIN user_profile t2 on t1.device_id t2.device_id where university 浙江大学解法二:子查询 select device_id, question_id, result from question_practice_detail …

Android 性能优化系列:启动优化进阶

文章目录 启动速度优化的本质因素CPU 层面进行速度优化减少程序的指令数降低时钟周期时间降低每条指令的平均时间周期 缓存层面进行速度优化缓存的读写速度缓存的命中率 任务调度层面进行速度优化通过实时进程和普通进程了解任务调度机制原理进程生命周期 CPU 优化合理使用线程…

day67_mybatisplus

今日内容 零、 复习昨日 零、 复习昨日 一、MybatisPlus快速入门 [MyBatis-Plus](简介 | MyBatis-Plus (baomidou.com))&#xff08;简称 MP&#xff09;是一个 MyBatis的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。 官方…

InnoDB: Waiting for page_cleaner to finish flushing of buffer pool 解决方案

这个是因为linux系统时间&#xff0c;Mysql数据库时间&#xff0c;Mysql日志时间出现不一致导致的。 1、date -R 查询linux系统时间 中国标准时区东八区时区 2、mysql数据库的时间 3、在mysql的配置文件里面&#xff0c;定义好时间&#xff0c;时区一致。 问题解决。

前端Vue自定义商品评价页面单选多选标签tags组件单选多选按钮选择器picker组件

随着技术的发展&#xff0c;开发的复杂度也越来越高&#xff0c;传统开发方式将一个系统做成了整块应用&#xff0c;经常出现的情况就是一个小小的改动或者一个小功能的增加可能会引起整体逻辑的修改&#xff0c;造成牵一发而动全身。 通过组件化开发&#xff0c;可以有效实现…

群晖折腾记5—docker安装emby开启核显

硬解的前提条件 Emby为正版 带核显的白裙或者已经被正确驱动的黑裙 开心版本不在讨论范围之内 需要的目录有/config /mnt/share1 /mnt/share2&#xff0c;自己创建对应的目录即可 打开ssh sudo -i输入下面命令首先判断群晖是否有核显驱动&#xff0c;白裙使用有带核显cpu的可…

关于新版本selenium定位元素报错:‘WebDriver‘ object has no attribute ‘find_element_by_id‘等问题

由于一段时间没有使用Selenium&#xff0c;当再次使用时发现之前写的Selenium元素定位的代码运行之后会报错&#xff0c;发现是Selenium更新到新版本&#xff08;4.x版本&#xff09;后&#xff0c;以前的一些常用的代码的语法发生了改变&#xff0c;当然如果没有更新过或是下载…

VS2022 Fortran调用lapack 64位库

首先&#xff0c;可以在官网下载以下lib 下载64位的&#xff0c;然后就是添加文件所在的文件夹&#xff0c;以及添加lib&#xff0c;就可以直接使用lapack中的函数&#xff0c;但是现在Oneapi中集成了lapack库&#xff0c;所以可以直接调用&#xff0c;如下所示。 1. 首先&…

MongoDB 事务与数据落盘

文章目录 概要一、持久性1.1、journal log刷盘机制1.2、数据刷盘机制1.3、复制集下的写安全机制 二、隔离性总结 概要 MongoDB并不像MySQL一样天然支持多文档事务&#xff0c;其演变过程如下&#xff1a; MongoDB4.0之前只支持单文档事务&#xff0c;在单个文档上支持ACID原子…

S32K14x FlexCAN入门

每个系列S32K14x支持的邮箱个数。 基本每个系列的FlexCAN0可以支持32个报文缓存和支持CANFD。 中断源 mail 最多有32个mail • 灵活的消息缓冲区 (MB)&#xff0c;总共 32 个消息缓冲区&#xff0c;数据长度为 8 字节 每个&#xff0c;可配置为 Rx 或 Tx 过滤掩码功能 强…

MyBatis中的缓存介绍与示例

目录 什么是缓存&#xff1f; 一级缓存 实例效果 二次缓存 示例效果 什么是缓存&#xff1f; 在用户访问相同数据时&#xff0c;需要对数据库多次访问&#xff0c;导致产生大量IO、读写硬盘的操作&#xff0c;效率低下&#xff0c;有了缓存首次访问时&#xff0c;查询到数…

【AI 绘图】Stable Diffusion WebUI 本地安装教程(Windows,兼容 NVIDIA、AMD 显卡)

文章目录 硬性要求Stable Diffusion 简介Stable Diffusion WebUI 简介1. 安装 Python 3.10.6&#xff08;较新版本的 Python 不支持 torch&#xff09;2. 安装 Git3. 下载 stable-diffusion-webui 存储库&#xff08;此步二选一&#xff09;3.1 NVIDIA GPU3.2 AMD GPU 4. webui…

Unity 3D 刚体初步

Unity 3D 中的 Rigidbody &#xff0c;刚体&#xff0c;是用来模拟物理特性&#xff0c;模拟推力与扭力&#xff0c;实现现实世界中的物理学现象。 把在外力作用下&#xff0c;物体的形状和大小保持不变&#xff0c;而且内部各部分相对位置保持恒定&#xff08;没有形变&#…

2.zabbxi操作和设置

文章目录 zabbxi操作和设置添加zabbix-agent客户端web端添加客户端 自定义监控模板&#xff08;面试&#xff09;监控模板下载地址案例1案例2 设置邮件报警自动注册和自动发现自动发现&#xff08;对于agent是被动模式&#xff09;自动注册&#xff08;对于agent是主动模式&…

把同组人做的工作写在自己简历上,算造假吗?知道这个需求不是我做的人,这个世界可能不超过10个人!...

把同组人做的东西写在自己简历上&#xff0c;算造假吗&#xff1f; 一位网友问&#xff1a; 同组人做的需求&#xff0c;需求细节我完全可以讲得清楚。知道这个需求不是我做的人&#xff0c;全世界可能不超过10个人&#xff0c;我把这个需求写在自己简历上算简历造假吗&#xf…

go数据结构之slice与map

1. 切片 1. 切片结构定义 type slice struct {array unsafe.Pointerlen intcap int }array:引用的底层数组&#xff0c;动态数组&#xff0c;可以修改 如果多个切片的array指针指向同一个动态数组&#xff0c;则它们都可以对底层这个动态数组元素进行修改。 len:&#xf…