recursive mutex的使用场景和场景代码

递归互斥锁:允许一个任务获取多次锁,而不会导致任务挂起。

多层嵌套的函数调用中保护同一个资源

在一个复杂的软件模块中,可能存在多层函数调用,而最内层和最外层的函数都需要访问同一个共享资源(如外设、全局数据结构)。为了防止在调用过程中被其他任务抢占并破坏数据,每一层都可能需要加锁。

  • 问题所在:如果外层函数已经获取了普通互斥锁,然后调用了内层函数。内层函数再次尝试获取同一个锁时,会因为锁已被当前任务持有而阻塞,导致整个调用链卡死,形成死锁。

  • 解决方案:使用递归互斥锁,内层函数可以安全地再次获取锁,而不会阻塞。

SemaphoreHandle_t xRecursiveMutex;

// 底层硬件访问函数

void HAL_UART_WriteByte(uint8_t data) {

// 内层函数也需要加锁,确保操作的原子性

if (xSemaphoreTakeRecursive(xRecursiveMutex, portMAX_DELAY) == pdTRUE) {

// 执行实际的UART寄存器操作

// USART_SendData(USART1, data);

xSemaphoreGiveRecursive(xRecursiveMutex);

}

}

// 上层逻辑函数

void vSendMessage(char *msg) {

// 外层函数先获取锁

if (xSemaphoreTakeRecursive(xRecursiveMutex, portMAX_DELAY) == pdTRUE) {

// 发送字符串的每个字节

while (*msg) {

// 调用内层函数,它会再次获取同一个锁

HAL_UART_WriteByte(*msg++);

}

xSemaphoreGiveRecursive(xRecursiveMutex);

}

}

NOTE:

void HAL_UART_WriteByte(uint8_t data) 担心其他的地方会调用这个接口,导致最上层的没有xSemaphoreTakeRecursive没有锁住公共部分。这个时候就需要递归互斥锁。

递归函数中需要加锁

这是最典型、最直观的应用场景。当一个函数直接或间接地调用自身(递归)时,如果该函数内部需要获取同一个互斥锁来保护共享资源,就必须使用递归互斥锁。

  • 问题所在 :如果在递归函数中使用普通互斥锁,第一次调用时成功获取了锁,但在锁还未释放时,函数又调用了自身。第二次调用会尝试再次获取同一个锁,因为该锁已被当前任务持有,普通互斥锁会导致任务永久阻塞,即死锁

  • 解决方案:递归互斥锁允许同一个任务多次"加锁",只需确保"解锁"次数与"加锁"次数相同即可。

// 假设有一个递归互斥锁句柄

SemaphoreHandle_t xRecursiveMutex;

// 递归函数,例如遍历树形结构

void vRecursiveFunction(int depth) {

// 每次进入函数都获取锁

if (xSemaphoreTakeRecursive(xRecursiveMutex, portMAX_DELAY) == pdTRUE) {

// --- 临界区开始 ---

// 安全地访问或修改受保护的共享数据结构

// ...

// --- 临界区结束 ---

if (depth > 0) {

// 递归调用自身,此时会再次获取锁,但不会死锁

vRecursiveFunction(depth - 1);

}

// 每次退出函数都释放锁

xSemaphoreGiveRecursive(xRecursiveMutex);

}

}

相关推荐
未来之窗软件服务4 小时前
计算机二级[英文]-C 字符串移动—东方仙盟
c语言·开发语言·仙盟创梦ide·东方仙盟
是隼人9 小时前
buuctf-pwn bypwn(ret2shellcode)题解(学习过程持续更新)
c语言·学习·安全·pwn入门·ctf入门
T1mzhou10 小时前
ARM64 Linux 6.10内核启动流程6-psci.c和ATF/U-Boot 的电源接口
linux·服务器·c语言
是隼人10 小时前
buuctf-pwn PWN2(整数溢出)题解(学习过程持续更新)
c语言·学习·安全·pwn入门·ctf入门
LuminousCPP11 小时前
数据结构 - 排序(二):快速排序从错误初版到优化版|双指针划分 + 三数取中 + 小区间插入优化
c语言·数据结构·笔记·算法·排序算法
竞赛考级题库11 小时前
202606 青少年等级考试C/C++真题一级 建议答题时长:60min
java·c语言·c++
迷茫、Peanut11 小时前
C语言混合链接
c语言
wdfk_prog12 小时前
RT-Thread Kconfig 配置明明是 y,为什么 rtconfig.h 就是不生成?一次 `_PATH` 后缀踩坑复盘
c语言
是隼人12 小时前
buuctf-pwn jarvisoj_level5(64位ret2libc)题解(学习过程持续更新)
c语言·学习·安全·pwn入门·ctf入门
Suxing913 小时前
C语言基础分享:C语言文件操作:从“写日记”到“拍电影”的存盘指南
c语言·开发语言