独占访问保护
互斥锁确保同一时刻只有一个任务能够持有锁并访问临界区资源, 防止多个任务同时修改共享数据导致的数据不一致问题。
互斥锁用于保护共享资源,确保同一时刻只有一个任务进入临界区, 避免并发访问导致的数据冲突与不一致问题。
互斥锁是任务同步的核心机制
互斥锁(Mutex)是一种用于保护共享资源的同步机制,确保同一时刻只有一个任务能够进入临界区访问资源。 当任务需要访问共享资源时,必须先获取互斥锁,访问完成后释放锁。 如果锁已被其他任务持有,当前任务将阻塞等待,直到锁被释放。
互斥锁确保同一时刻只有一个任务能够持有锁并访问临界区资源, 防止多个任务同时修改共享数据导致的数据不一致问题。
临界区是指访问共享资源的代码段,互斥锁通过加锁和解锁机制 明确定义临界区的边界,确保资源访问的原子性和完整性。
竞争条件是指多个任务同时访问和修改共享资源时产生的不可预测结果。 互斥锁通过串行化资源访问,消除竞争条件,保证数据一致性。
互斥锁不仅保护资源,还起到任务同步的作用。 任务通过获取和释放锁来协调执行顺序,确保共享资源的安全访问。
HRTOS 如何实现互斥锁同步
在 HRTOS 中,互斥锁的实现围绕互斥锁初始化、加锁操作、解锁操作和锁状态管理四个核心环节展开。 每个环节都经过精心设计,确保同步的高效性和可靠性。
初始化内容:创建互斥锁对象,设置初始状态为未锁定
所有权管理:记录当前持有锁的任务ID
等待队列:初始化等待获取锁的任务队列
优先级继承:启用优先级继承机制防止优先级反转
锁检查:检查互斥锁当前状态,判断是否可获取
获取成功:更新锁状态,记录当前任务为锁持有者
获取失败:将当前任务加入等待队列,阻塞等待
优先级提升:如启用优先级继承,提升锁持有者优先级
所有权验证:验证当前任务是否为锁持有者
状态更新:清除锁状态,释放资源控制权
优先级恢复:恢复锁持有任务的原始优先级
任务唤醒:从等待队列中选择一个任务唤醒并获取锁
状态跟踪:维护锁的锁定状态和持有者信息
等待队列:管理所有等待获取锁的任务
死锁预防:设计合理的锁获取顺序避免死锁
优先级继承:动态调整任务优先级解决优先级反转
互斥锁从初始化到释放的完整执行路径
互斥锁同步的完整实现
task1 任务函数,通过互斥锁保护临界区访问
#include "hrtos.h"
#define MUTEX_ID 0
sbit LED_T1 = P1^0;
sbit LED_T2 = P1^1;
sbit LED_CS = P1^2;
void task1(void)
{
while(1)
{
if(os_mutex_lock(MUTEX_ID))
{
LED_T1 = 1;
LED_CS = 1;
os_delay(3);
LED_T1 = 0;
LED_CS = 0;
os_mutex_unlock(MUTEX_ID);
}
else
{
LED_T1 = ~LED_T1;
}
os_delay(4);
}
}
task2 任务函数,与 task1 竞争互斥锁资源
void task2(void)
{
while(1)
{
if(os_mutex_lock(MUTEX_ID))
{
LED_T2 = 1;
LED_CS = 1;
os_delay(3);
LED_T2 = 0;
LED_CS = 0;
os_mutex_unlock(MUTEX_ID);
}
else
{
LED_T2 = ~LED_T2;
}
os_delay(4);
}
}
hrtos_main 函数,初始化互斥锁并创建竞争任务
void hrtos_main(void)
{
os_mutex_init(MUTEX_ID);
os_task_create((unsigned int)task1, 1, 3, 5);
os_task_create((unsigned int)task2, 2, 2, 5);
}
示例执行后的预期行为
使用本示例时需要关注的关键点
必须确保每次成功获取锁后都释放锁,避免死锁。 建议在临界区代码中使用 try-finally 或类似机制保证锁的释放。
临界区应尽可能短,只包含必要的共享资源访问代码。 过长的临界区会降低系统并发性能,增加任务阻塞时间。
当低优先级任务持有锁而高优先级任务等待时,可能发生优先级反转。 HRTOS 互斥锁支持优先级继承机制,可有效缓解此问题。
避免循环等待锁的情况,建议按照固定顺序获取多个锁。 在复杂场景中,可使用超时机制防止无限等待。
深入学习的相关资源