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);

}

}

相关推荐
caimouse3 小时前
ReactOS 窗口系统架构分析
服务器·c语言
caimouse3 小时前
ReactOS 图形系统分析(46):DC 工具 — dcutil.c
c语言·开发语言
BreezeJuvenile3 小时前
嵌入式C语言常见考察点(2)
c语言·嵌入式
caimouse3 小时前
ReactOS 图形系统分析(50):画笔子系统 — pen.c
c语言·开发语言·stm32
caimouse4 小时前
ReactOS 图形系统分析(48):弧线绘制 — arc.c
c语言·开发语言
cypking5 小时前
Objective-C 语法完整学习手册(小白自学 + 开发备查)
c语言·开发语言·学习·objective-c
wuyk55514 小时前
98.C语言易混难点:字符数组与字符串指针的底层差异
c语言·开发语言·c++·stm32·嵌入式硬件·算法
wp123_114 小时前
IPX8 防水 Type‑C连接器:安费诺 124018792112A 与 TONEVEE TY48087‑24A 技术梳理
c语言·开发语言
2401_8628808220 小时前
数据结构 --- 栈
c语言·数据结构·算法