RT_thread(五)线程间同步之互斥量


互斥量

互斥量又叫相互排斥的信号量,是一种特殊的二值信号量。互斥量类似于只有一个车位的停车场:当有一辆车进入的时候,将停车场大门锁住,其他车辆在外面等候。当里面的车出来时,将停车场大门打开,下一辆车才可以进入。


一、互斥量工作机制

互斥量的状态只有两种,开锁或闭锁。用互斥量处理不同线程对临界资源的同步访问时,获取互斥量才可以对资源进行访问,互斥量的所有权只能由一个线程所掌握,其他线程无法干涉。当线程1持有时,互斥量的状态为闭锁状态,其他线程禁止访问;线程1释放互斥量时,互斥量的状态为开锁状态,线程1失去所有权,所有线程要使用资源,按照优先级获取互斥量。

1、优先级反转问题

优先级反转问题:当使用信号量时,高优先级的线程尝试通过信号量访问资源时,如果当信号量已经被低优先级访问,低优先级运行程序时被中优先级线程卡住,无法运行完释放信号量,导致高优先级无法从低优先级手中拿取信号量,违背了线程按照优先级大小使用资源的初衷。
如果低优先级被更高优先级卡住,无法运行完,这不算优先级反转

2.优先级继承机制

优先级继承算法:暂时提高某个占有某种资源的低优先级线程的优先级,使之与在所有等待该资源的线程中优先级最高那个线程的优先级相等,而当这个低优先级线程执行完毕释放该资源时,优先级重新回到初始设定值。因此,继承优先级的线程避免了系统资源被任何中间优先级的线程抢占。

3.示例图分析

1.优先级反转

优先级反转(A线程表示这个大哥当不了)
见图分析

在这里插入图片描述
系统中有A、B、C三个线程,优先级依次降低

  1. A、B线程等待事件触发,C线程被事件触发,C获取共享资源M
  2. A线程被事件触发,插入就绪链表,因为最高优先级,A线程运行尝试获取M资源,因为M被C线程占据,A线程挂起等待C线程释放M
  3. C线程运行一段时间后,B线程就绪,优先级比C线程高并且不需要使用M资源,C线程让出处理器,B线程运行
  4. B线程运行完,A线程启动无M资源挂起(相当于A线程没运行),C线程继续运行知道释放M资源
  5. A线程启动获得M资源,继续运行
    总结A线程因为M资源的原因,无法运行,而占据M资源的C线程,因为优先级低,需要让出处理器给不需要M资源的B线程。A线程表示我等C线程就算了,毕竟M资源(人质)在他手上,B线程你算什么,要老子等你

2.优先级继承

优先级继承(C线程的狐假虎威)
见图分析

在这里插入图片描述
系统中有A、B、C三个线程,优先级依次降低

  1. A、B线程等待事件触发,C线程被事件触发,C获取共享资源M
  2. A线程被事件触发,插入就绪链表,因为最高优先级,A线程运行尝试获取M资源,因为M被C线程占据,A线程挂起等待C线程释放M
  3. 将C线程的优先级存在互斥量控制块中的original_priority,A线程给C线程相同的优先级
  4. B线程就绪,C优先级=A优先级>B优先级,B无法抢占,C线程继续运行
  5. C线程运行完释放M资源,并且取回自己优先级,按照优先级链表排序,A线程运行,A获取M资源
  6. A线程运行完,才轮到B线程
    总结A线程因为M资源在C线程手中,忍痛给C线程相同优先级,C线程狐假虎威让B线程不敢妄动,B线程表示看在A线程面子上,让你一次

4代码分析

1.互斥量控制块

互斥量总控制台

struct rt_mutex
{
   
    struct rt_ipc_object parent;     //继承自 ipc_object 类

    rt_uint16_t          value;       //互斥量的值

    rt_uint8_t           original_priority;    //持有线程的原始优先级
    rt_uint8_t           hold;                //持有线程的持有次数

    struct rt_thread    *owner;               //当前拥有互斥量的线程
};
typedef struct rt_mutex *rt_mutex_t;

在这里插入图片描述

2互斥量管理图

代码来自ipc.c

在这里插入图片描述

3初始化和脱离

初始化
静态互斥量对象的内存是在系统编译时由编译器分配的,一般放于读写数据段或未初始化数据段中。在使用这类静态互斥量对象前,需要先进行初始化

rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag)
{
   
    /* parameter check */
    RT_ASSERT(mutex != RT_NULL);//参数核查是否为互斥量

    /* init object */
    rt_object_init(&(mutex->parent.parent), RT_Object_Class_Mutex, name);//初始化互斥量对象

    /* init ipc object */
    rt_ipc_object_init(&(mutex->parent));//初始化ipc对象

    mutex->value = 1;                      //互斥量值为1
    mutex->owner = RT_NULL;                //持有互斥量线程为空
    mutex->original_priority = 0xFF;       //持有线程原始优先级为0xff
    mutex->hold  = 0;                      //持有数为0

    /* set flag */
    mutex->parent.parent.flag = flag;  //设置标志位

    return RT_EOK;
}
RTM_EXPORT(rt_mutex_init);

脱离(不删内存)从对象容器中脱离

rt_err_t rt_mutex_detach(rt_mutex_t mutex)
{
   
    /* parameter check */
    RT_ASSERT(mutex != RT_NULL);//参数核查是否为互斥量
    RT_ASSERT(rt_object_get_type(&mutex->parent.parent) == RT_Object_Class_Mutex);//判断对象是否为互斥量
    RT_ASSERT(rt_object_is_systemobject(&mutex->parent
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值