同步与互斥(三)

一、递归锁

/* 创建一个递归锁,返回它的句柄。
* 此函数内部会分配互斥量结构体
* 返回值: 返回句柄,非NULL表示成功
*/
SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void );/* 释放 */
BaseType_t xSemaphoreGiveRecursive( SemaphoreHandle_t xSemaphore );/* 获得 */
BaseType_t xSemaphoreTakeRecursive(SemaphoreHandle_t xSemaphore,TickType_t xTicksToWait
);

static void vTakeTask( void *pvParameters )
{const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL );	BaseType_t xStatus;int i;/* 无限循环 */for( ;; ){	/* 获得递归锁: 上锁 */xStatus = xSemaphoreTakeRecursive(xMutex, portMAX_DELAY);//上锁成功printf("Task1 take the Mutex in main loop %s\r\n", \(xStatus == pdTRUE)? "Success" : "Failed");/* 阻塞很长时间, 让另一个任务执行, * 看看它有无办法再次获得递归锁 */vTaskDelay(xTicksToWait);//任务一挂起,任务二就绪运行for (i = 0; i < 10; i++){/* 获得递归锁: 上锁 */xStatus = xSemaphoreTakeRecursive(xMutex, portMAX_DELAY);printf("Task1 take the Mutex in sub loop %s, for time %d\r\n", \(xStatus == pdTRUE)? "Success" : "Failed", i);/* 释放递归锁 */xSemaphoreGiveRecursive(xMutex);}/* 释放递归锁 */xSemaphoreGiveRecursive(xMutex);}
}
static void vGiveAndTakeTask( void *pvParameters )
{const TickType_t xTicksToWait = pdMS_TO_TICKS( 10UL );	BaseType_t xStatus;/* 尝试获得递归锁: 上锁 */xStatus = xSemaphoreTakeRecursive(xMutex, 0);//任务一上锁了,任务二上锁失败//0说明不会等,上锁失败直接返回// xMutex = xSemaphoreCreateRecursiveMutex( );同一把锁printf("Task2: at first, take the Mutex %s\r\n", \(xStatus == pdTRUE)? "Success" : "Failed");/* 如果失败则监守自盗: 开锁 */if (xStatus != pdTRUE){/* 无法释放别人持有的锁 */xStatus = xSemaphoreGiveRecursive(xMutex);//解锁别人创建的锁失败printf("Task2: give Mutex %s\r\n", \(xStatus == pdTRUE)? "Success" : "Failed");}printf("task2\r\n");/* 如果无法获得, 一直等待 */xStatus = xSemaphoreTakeRecursive(xMutex, portMAX_DELAY);//任务二一直堵在这,下不去了//xStatus = xSemaphoreTakeRecursive(xMutex, 0);//改成0就能运行下去printf("Task2: and then, take the Mutex %s\r\n", \(xStatus == pdTRUE)? "Success" : "Failed");/* 无限循环 */for( ;; ){	/* 什么都不做 */vTaskDelay(xTicksToWait);}
}

 main函数:

/* 递归锁句柄 */
SemaphoreHandle_t xMutex;int main( void )
{prvSetupHardware();/* 创建递归锁 */xMutex = xSemaphoreCreateRecursiveMutex( );if( xMutex != NULL ){/* 创建2个任务: 一个上锁, 另一个自己监守自盗(开别人的锁自己用)*/xTaskCreate( vTakeTask, "Task1", 1000, NULL, 2, NULL );xTaskCreate( vGiveAndTakeTask, "Task2", 1000, NULL, 1, NULL );/* 启动调度器 */vTaskStartScheduler();}else{/* 无法创建递归锁 */}/* 如果程序运行到了这里就表示出错了, 一般是内存不足 */return 0;
}

A:任务1优先级最高,先运行,获得递归锁
B:任务1阻塞,让任务2得以运行


C:任务2运行,看看能否获得别人持有的递归锁:不能
D:任务2故意执行"give"操作,看看能否释放别人持有的递归锁:不能


E:任务2等待递归锁
F:任务1阻塞时间到后继续运行,使用循环多次获得、释放递归锁
递归锁在代码上实现了:谁持有递归锁,必须由谁释放。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenEular23.09(欧拉)操作系统为企业搭建独立的K8S集群环境,详细流程+截图

一.环境&#xff1b; win10&#xff0c;vmware16 pro&#xff0c;openeular23.09 集群模式&#xff1a;一主二从 主机硬件配置 主机名IP角色CPU内存硬盘k8s-master01192.168.91.100master4C4G40Gk8s-worker02192.168.91.101worker(node)4C4G40Gk8s-worker03192.168.91.102wor…

Resnet BatchNormalization 迁移学习

时间&#xff1a;2015 网络中的亮点&#xff1a; 超深的网络结构&#xff08;突破1000层&#xff09;提出residual模块使用Batch Normalization加速训练&#xff08;丢弃dropout&#xff09; 层数越深效果越好&#xff1f; 是什么样的原因导致更深的网络导致的训练效果更差呢…

计算机组成原理知识总结

目录 第一章、计算机系统概述知识框架&#xff1a;1.冯诺依曼机和存储程序的概念&#xff1f;2.计算机的工作过程&#xff1f;3.在计算机系统结构中&#xff0c;什么是编译&#xff1f;什么是解释&#xff1f;4.描述一下指令执行过程&#xff1f;1) 取指令&#xff1a; PC 一&g…

【Redis技术专区】「原理分析」探讨Redis 6.0为何需要启用多线程?

探讨Redis 6.0为何需要启用多线程 背景介绍开启多线程多线程的CPU核心配置IO多线程模式单线程处理方式多线程处理方式 为什么要开启多线程&#xff1f;充分利用多核CPU提高网络I/O效率响应现代应用需求 多线程实现启用多线程 最后总结 背景介绍 在Redis 6.0版本中&#xff0c;…

vue+ts element-plu是页码器根据屏幕宽度变化,解决刷新后初始化值问题

实现思路&#xff1a;组件挂载后执行初始化操作&#xff0c;初始化添加事件监听器&#xff0c;当浏览器窗口大小发生变化时会调用这个函数handleResize <el-pagination v-model:current-page"currentPage" background :total"total" layout"prev,…

【Java】ThreadLocal原理与使用场景

ThreadLocal原理&#xff1a; 字段&#xff1a; //ThreadLocal对象的哈希码 private final int threadLocalHashCode nextHashCode();//生成ThreadLocal对象的哈希码时&#xff0c;需要用到该对象&#xff0c;从0开始 private static AtomicInteger nextHashCode new Atomic…

数据结构和算法-B树的插入和删除

文章目录 B树的插入小结B树的删除小结 B树的插入 首先将根节点的关键字个数填满&#xff0c;填满后再分开成树 分开的规则 此时插入90&#xff0c;从根节点依次查找&#xff0c;然后插入到终端节点的关键字中 插入同上&#xff0c;注意此时在终端节点插入要符合终端节点的大…

STM32+Codesys工业软件PLC解决方案

工业控制系统在现代制造和自动化领域扮演着关键角色, 基于IEC 61131-3 标准的控制器编程开发软件平台CODESYS&#xff0c;适用于多种行业的控制系统的开发,使用户方便快捷地对自动化工程进行编程和配置&#xff0c;完成项目开发、软件测试和应用调试。 本次STM32联合合作伙伴C…

Linux基础知识学习2

tree命令的使用 可以看到dir2目录下的这些文件&#xff0c;要想显示dir2的具体结构&#xff0c;可用tree命令 mv命令 它可以实现两个功能 1.将文件移动到另一个目录中 2.对某一个文件进行重命名 1.将文件移动到另一个目录中 这里将dir1中的2.txt移动到他的子目录dir3中 执行…

2022年全球运维大会(GOPS上海站)-核心PPT资料下载

一、峰会简介 GOPS 主要面向运维行业的中高端技术人员&#xff0c;包括运维、开发、测试、架构师等群体。目的在于帮助IT技术从业者系统学习了解相关知识体系&#xff0c;让创新技术推动社会进步。您将会看到国内外知名企业的相关技术案例&#xff0c;也能与国内顶尖的技术专家…

S7-1200 PLC回原方式详细解读(SCL代码)

S7-1200PLC脉冲轴位置控制功能块的介绍,可以查看下面链接文章: https://rxxw-control.blog.csdn.net/article/details/135299302https://rxxw-control.blog.csdn.net/article/details/135299302脉冲轴工艺对象组态设置介绍 https://rxxw-control.blog.csdn.net/article/det…

【小沐学NLP】Python实现TF-IDF算法(nltk、sklearn、jieba)

文章目录 1、简介1.1 TF1.2 IDF1.3 TF-IDF2.1 TF-IDF(sklearn)2.2 TF-IDF(nltk)2.3 TF-IDF(Jieba)2.4 TF-IDF(python) 结语 1、简介 TF-IDF&#xff08;term frequency–inverse document frequency&#xff09;是一种用于信息检索与数据挖掘的常用加权技术。TF是词频(Term Fr…