H
HRTOS
Synchronization Core

互斥锁

互斥锁用于保护共享资源,确保同一时刻只有一个任务进入临界区, 避免并发访问导致的数据冲突与不一致问题。

核心特性

  • 独占访问保护
  • 临界区资源管理
  • 避免竞争条件
  • 任务同步机制

应用场景

  • 共享变量访问
  • 外设访问控制
  • 临界区保护
  • 任务执行顺序控制
同步方式 加锁 → 独占访问 → 解锁
保护机制 临界区资源互斥访问
Principle

原理说明

互斥锁是任务同步的核心机制

互斥锁(Mutex)是一种用于保护共享资源的同步机制,确保同一时刻只有一个任务能够进入临界区访问资源。 当任务需要访问共享资源时,必须先获取互斥锁,访问完成后释放锁。 如果锁已被其他任务持有,当前任务将阻塞等待,直到锁被释放。

独占访问保护

互斥锁确保同一时刻只有一个任务能够持有锁并访问临界区资源, 防止多个任务同时修改共享数据导致的数据不一致问题。

临界区资源管理

临界区是指访问共享资源的代码段,互斥锁通过加锁和解锁机制 明确定义临界区的边界,确保资源访问的原子性和完整性。

避免竞争条件

竞争条件是指多个任务同时访问和修改共享资源时产生的不可预测结果。 互斥锁通过串行化资源访问,消除竞争条件,保证数据一致性。

任务同步机制

互斥锁不仅保护资源,还起到任务同步的作用。 任务通过获取和释放锁来协调执行顺序,确保共享资源的安全访问。

核心判断: Mutex = 加锁 → 独占访问 → 解锁 → 任务调度恢复, 是实现任务间资源保护和同步的关键机制。
HRTOS Implementation

HRTOS 实现机制

HRTOS 如何实现互斥锁同步

在 HRTOS 中,互斥锁的实现围绕互斥锁初始化、加锁操作、解锁操作和锁状态管理四个核心环节展开。 每个环节都经过精心设计,确保同步的高效性和可靠性。

互斥锁初始化

初始化内容:创建互斥锁对象,设置初始状态为未锁定

所有权管理:记录当前持有锁的任务ID

等待队列:初始化等待获取锁的任务队列

优先级继承:启用优先级继承机制防止优先级反转

加锁操作

锁检查:检查互斥锁当前状态,判断是否可获取

获取成功:更新锁状态,记录当前任务为锁持有者

获取失败:将当前任务加入等待队列,阻塞等待

优先级提升:如启用优先级继承,提升锁持有者优先级

解锁操作

所有权验证:验证当前任务是否为锁持有者

状态更新:清除锁状态,释放资源控制权

优先级恢复:恢复锁持有任务的原始优先级

任务唤醒:从等待队列中选择一个任务唤醒并获取锁

锁状态管理

状态跟踪:维护锁的锁定状态和持有者信息

等待队列:管理所有等待获取锁的任务

死锁预防:设计合理的锁获取顺序避免死锁

优先级继承:动态调整任务优先级解决优先级反转

Workflow

工作流程

互斥锁从初始化到释放的完整执行路径

1互斥锁初始化:hrtos_main 中调用 os_mutex_init 创建互斥锁对象
2任务创建:创建 task1 和 task2 两个竞争任务
3尝试加锁:任务调用 os_mutex_lock 尝试获取互斥锁
4竞争或阻塞:成功则进入临界区,失败则阻塞等待
5进入临界区:独占访问共享资源,执行临界区代码
6释放锁:调用 os_mutex_unlock 释放互斥锁,唤醒等待任务
hrtos_main → os_mutex_init → os_task_create(task1) → os_task_create(task2) → os_mutex_lock → 竞争/阻塞 → 临界区访问 → os_mutex_unlock → 任务调度恢复
Core Code

核心代码

互斥锁同步的完整实现

任务1实现

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

任务2实现

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);
}
Expected Result

运行结果

示例执行后的预期行为

LED_T1 状态 task1 获取锁时点亮,释放后熄灭
LED_T2 状态 task2 获取锁时点亮,释放后熄灭
LED_CS 状态 临界区指示,表示资源被独占访问
任务竞争 task1 和 task2 通过互斥锁实现交替访问
系统本质: 本示例验证 HRTOS 互斥锁机制:两个任务通过互斥锁竞争临界区资源, 确保同一时刻只有一个任务访问共享资源,避免数据冲突。
Important Notes

注意事项

使用本示例时需要关注的关键点

锁的获取与释放

必须确保每次成功获取锁后都释放锁,避免死锁。 建议在临界区代码中使用 try-finally 或类似机制保证锁的释放。

临界区范围控制

临界区应尽可能短,只包含必要的共享资源访问代码。 过长的临界区会降低系统并发性能,增加任务阻塞时间。

优先级反转

当低优先级任务持有锁而高优先级任务等待时,可能发生优先级反转。 HRTOS 互斥锁支持优先级继承机制,可有效缓解此问题。

死锁预防

避免循环等待锁的情况,建议按照固定顺序获取多个锁。 在复杂场景中,可使用超时机制防止无限等待。