鸿蒙Hi3861学习九-Huawei LiteOS(互斥锁)

news2024/11/18 4:48:55

一、简介

        互斥锁又被称为互斥型信号量,是一种特殊的二值信号量,用于实现对共享资源的独占式处理

        任意时刻互斥锁的状态只有两种:开锁闭锁

        当有任务占用公共资源时,互斥锁处于闭锁状态,这个任务获得该互斥锁的使用权。

        当该任务释放公共资源时,互斥锁被开锁,任务失去该互斥锁的所有权。

        当一个任务持有互斥锁时其他任务将不能再对该互斥锁进行开锁或持有

        多任务环境下,往往存在多个任务竞争同一共享资源的应用场景。互斥锁可被用于对共享资源的保护,从而实现独占式访问。另外,互斥锁可以解决信号量存在的优先级翻转问题

        更多关于互斥锁的概念以及优先级翻转问题的概念,可以参考如下链接:FreeRTOS学习五(信号量)_freertos信号量用法_t_guest的博客-CSDN博客

Mutex Management 

二、 运行机制

        多任务环境下会存在多个任务访问同一公共资源的场景,而有些公共资源时非共享的,需要任务进行独占式处理。此时,就需要互斥锁出面了。

        用互斥锁处理非共享资源的同步访问时,如果有任务访问该资源,则互斥锁切换为闭锁状态。此时,其他任务如果想访问这个公共资源,则会被阻塞直到互斥锁被持有该锁的任务释放后,其他任务才能重新访问该公共资源,并且互斥锁会再次转换为闭锁状态。如此确保在同一时刻,只有一个任务正在访问这个公共资源,保证了公共资源操作的完整性

        优先级翻转,之前的文章中已经介绍过了,这里就不再过多介绍。有兴趣可以看上述的链接。

 三、API介绍

      osMutexNew

        函数功能:

        创建互斥锁。不可在中断中使用

        函数原型:

osMutexId_t osMutexNew(const osMutexAttr_t *attr)

        参数:

        attr:属性,自定义内存时使用。默认NULL

        返回值:

        锁标识符

        实例:

osMutexId_t mutex_id;
mutex_id = osMutexNew(NULL);

      osMutexAcquire

        函数功能:

        获取互斥锁。如果为闭锁状态,则阻塞任务等待直到超时为止。如果为开锁状态,则切换为闭锁状态。不可在中断中使用

        函数原型:

osStatus_t osMutexAcquire(osMutexId_t mutex_id, uint32_t timeout)

        参数:

        mutex_id:锁标识符。创建锁osMutexNew时获取

        timeout:等待超时时间。osWaitForever死等

        返回值:

        osOK:成功

        其他值:失败

        实例:

osMutexId_t mutex_id;
osMutexAcquire(mutex_id, osWaitForever);

      osMutexRelease

        函数功能:

        释放锁。如果锁为闭锁状态,释放后才能被其他任务获取到。不可在中断中使用

        函数原型:

osStatus_t osMutexRelease(osMutexId_t mutex_id)

        参数:

        mutex_id:锁标识符。创建锁osMutexNew时获取。

        返回值:

        osOK:成功

        其他值:失败

        实例:

osMutexId_t mutex_id;
osMutexRelease(mutex_id);

      osMutexDelete

        函数功能:

        删除锁。不可在中断中使用。

        函数原型:

osStatus_t osMutexDelete(osMutexId_t mutex_id)

        参数:

        mutex_id:锁标识符。创建锁osMutexNew时获取。

        返回值:

        osOK:成功

        其他值:失败

        实例:

osMutexId_t mutex_id;
osMutexDelete(mutex_id);

四、实例

        创建三个任务,三个任务的优先级递增。同时操作互斥锁,看看结果如何。

#define LOG_I(fmt, args...)   printf("<%8ld> - [TIMER]:"fmt"\r\n",osKernelGetTickCount(),##args);
#define LOG_E(fmt, args...)   printf("<%8ld>-[TIMER_ERR]>>>>>>>>>>>>:"fmt"\r\n",osKernelGetTickCount(), ##args);

osMutexId_t mutex_id;

void HighPrioThread(void)
{
  osDelay(50U);

  while (1)
  {
    LOG_I("HighPrioThread get before");
    osMutexAcquire(mutex_id, osWaitForever);
    LOG_I("HighPrioThread get after");

    osDelay(50U);

    LOG_I("HighPrioThread mutex release before");
    osMutexRelease(mutex_id);
    LOG_I("HighPrioThread mutex release after");
  }
}

void MidPrioThread(void)
{
  osDelay(10U);

  while (1)
  {
    LOG_I("MidPrioThread get before");
    osMutexAcquire(mutex_id, osWaitForever);
    LOG_I("MidPrioThread get after");

    osDelay(100);

    LOG_I("MidPrioThread mutex release before");
    osMutexRelease(mutex_id);
    LOG_I("MidPrioThread mutex release after");
  }
}

void LowPrioThread(void)
{
  while (1)
  {
    LOG_I("LowPrioThread get before");
    osMutexAcquire(mutex_id, osWaitForever);
    LOG_I("LowPrioThread get after");

    osDelay(200U);

    LOG_I("LowPrioThread mutex release before");
    osMutexRelease(mutex_id);
    LOG_I("LowPrioThread mutex release after");
  }
}

void Hello_World(void)
{
    LOG_I("Test mutex");

    mutex_id = osMutexNew(NULL);
    if (mutex_id == NULL)
    {
        LOG_E("Falied to create Mutex!\n");
    }

    osThreadAttr_t attr;

    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 1024 * 4;

    attr.name = "HighPrioThread";
    attr.priority = osPriorityNormal2;

    if (osThreadNew((osThreadFunc_t)HighPrioThread, NULL, &attr) == NULL)
    {
        LOG_E("Falied to create HighPrioThread!\n");
    }

    attr.name = "MidPrioThread";
    attr.priority = osPriorityNormal1;

    if (osThreadNew((osThreadFunc_t)MidPrioThread, NULL, &attr) == NULL)
    {
        LOG_E("Falied to create MidPrioThread!\n");
    }

    attr.name = "LowPrioThread";
    attr.priority = osPriorityNormal;

    if (osThreadNew((osThreadFunc_t)LowPrioThread, NULL, &attr) == NULL)
    {
        LOG_E("Falied to create LowPrioThread!\n");
    }
}

        看结果:

         任务1优先级任务2优先级任务3优先级

        启动后,任务1延迟500ms执行任务2延迟100ms执行任务3不延迟

        注:以下编号与图片上编号对应

        1.任务3率先执行,先获取到互斥锁,使锁为闭锁状态。模拟操作共享数据。

        2.任务2延迟完成,开始执行,获取互斥锁,发现为闭锁状态,则挂起任务等待。

        3.任务1延迟完成,开始执行,获取互斥锁,发现为闭锁状态,则挂起任务等待。

        4.任务3数据操作完成,释放互斥锁。

        5.任务1因为优先级最高即使任务2先等待,但是还是任务1抢占到控制权然后获取互斥锁。然后开始操作数据。

        6.任务3继续执行。

        7.任务3获取互斥锁,发现为闭锁状态,则挂起任务等待。

        8.9。任务1继续执行

        10.任务1获取互斥锁。虽然任务1刚才释放了互斥锁,但是任务2一直在等待互斥锁,在任务1释放的瞬间就获取到互斥锁了。所以这里即使任务1优先级高,也无法获取到互斥锁。

        11.任务2模拟操作数据

        12.任务2操作数据完成,释放互斥锁。

        13.任务1因为优先级高,这里获取到互斥锁,模拟操作数据。

        这里可能会有疑问,为什么在10阶段,任务2明明优先级低,却能获取到互斥锁。而13这里任务3缺获取不到。这是因为在10阶段,任务2是在任务1释放互斥锁时,等待任务队列中优先级最高的任务。而13阶段,任务2在释放信号量时,任务1早已经在等待了。任务1是等待队列中优先级最高的。所以互斥锁才会被任务1截胡。

        从运行结果可以看出来,在同时等待互斥锁时,高优先级的任务总会有限获取到信号量,跟等待顺序是无关的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/503138.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

lua | 循环和函数的使用

目录 一、循环与流程控制 循环 流程控制 二、函数 函数 多返回值 可变参数 本文章为笔者学习分享 学习网站&#xff1a;Lua 基本语法 | 菜鸟教程 一、循环与流程控制 循环 lua语言提供了以下几种循环处理方式&#xff1a; 1.while 条件为true时&#xff0c;程序重复…

数据结构(六)—— 二叉树(7)构建二叉树

文章目录 如何使用递归构建二叉树1、创建一颗全新树&#xff08;题1-5&#xff09;2、在原有的树上新增东西&#xff08;题6&#xff09; 1 106 从 后序 与 中序 遍历序列构造二叉树2 105 从 前序 与 中序 遍历序列构造二叉树3 108 将有序数组转换为二叉搜索树&#xff08;输入…

施耐德电气 × 牛客:HR如何助力业务数字化转型?

历经一百八十多年的发展&#xff0c;施耐德电气从一家钢铁企业&#xff0c;进入电力与控制领域&#xff0c;再到如今成为全球能源管理和自动化领域的数字化专家&#xff0c;业务覆盖100多个国家&#xff0c;拥有近13万员工。 其背后离不开HR强大后盾的支撑&#xff0c;下面将独…

Linux文件系统目录有什么用?

学习文件系统的意义在于文件系统有很多设计思路可以迁移到实际的工作场景中&#xff0c;比如&#xff1a; MySQL 的 binlog 和 Redis AOF 都像极了日志文件系统的设计&#xff1b;B Tree用于加速磁盘数据访问的设计&#xff0c;对于索引设计也有通用的意义。 特别是近年来分布…

【Java|golang】1010. 总持续时间可被 60 整除的歌曲

在歌曲列表中&#xff0c;第 i 首歌曲的持续时间为 time[i] 秒。 返回其总持续时间&#xff08;以秒为单位&#xff09;可被 60 整除的歌曲对的数量。形式上&#xff0c;我们希望下标数字 i 和 j 满足 i < j 且有 (time[i] time[j]) % 60 0。 示例 1&#xff1a; 输入&…

【LangChain】如何本地部署基于chatGPT的实时文档和表格数据的助手,在自己的数据上构建chatGPT?

【LangChain】如何本地部署基于chatGPT的实时文档和表格数据的助手&#xff0c;在自己的数据上构建chatGPT 1 相关技术 &#xff08;1&#xff09;LangChain 是一个用于自然语言处理的 Python 库&#xff0c;它的目标是尝试简化自然语言处理任务&#xff0c;提高处理效率和准…

渲染对电脑伤害大吗_如何减少渲染伤机?

虽然说摄影穷三代&#xff0c;但想要自己的本地配置跟上自己的创作速度&#xff0c;高昂的硬件配置支出也可以让自己穷一段时间。CG制作过程中&#xff0c;渲染是必不可少的一步&#xff0c;而且这一步也是很吃“机器”的&#xff0c;那很多人也会担心&#xff0c;如果经常用自…

如何构建产品帮助中心?

据研究表明超过50%的互联网用户&#xff0c;更愿意使用网站中的自助服务支持去解决产品使用中的问题。那么这个时候在线帮助中心&#xff08;即在线帮助页面&#xff09;&#xff0c;就满足了用户这个需求。 在线帮助中心是一个丰富的知识库&#xff0c;可以指导企业的潜在客户…

asp.net+sqlserver漫画绘本借阅管理系统

摘 要1 第1章 系统概述5 1.1 研究背景5 1.2 研究的意义5 1.3 主要研究内容5 第2章 系统开发环境7 2.1 ASP.NET概述7 2.2 动态网站技术介绍8 2.3 数据库技术8 第3章 需求分析9 3.1 需求分析9 3.1.1 功能需求9 3.2 可行性分析9 3.2.1 可行性分析9 3.2.2 技术可行性9 3.2.3 运行可…

OpenCV4 学习指导1 —— Mat:最基本的图像容器

Mat: CV基本的数据结构 1、认识数字图像2、CV的发展历程3、Mat的基本结构3.1、Mat—浅拷贝3.2、Mat—深拷贝 4、颜色的表示方法5、创建Mat对象方法集合5.1、Mat类的常用成员函数5.2、Mat类的成员函数举例 6、Mat的输出样式7、Point 数据存储结构8、参考资源 1、认识数字图像 我…

Yolov8改进---注意力机制:Polarized Self-Attention,效果秒杀CBAM、SE

1. Polarized Self-Attention 论文:https://export.arxiv.org/pdf/2107.00782.pdf Polarized self-attention是一种改进的自注意力机制,旨在提高自注意力模型的效率和准确性。传统的自注意力机制通常需要计算所有位置对所有位置的注意力,这会导致计算复杂度的增加和模型的训…

君子签:助力高校毕业、就业协议电子签,打通就业最后一公里

据介绍&#xff0c;2023届全国普通高校毕业生规模预计达1158万人&#xff0c;同比增加82万人。毕业季即将来临&#xff0c;全国各大高校毕业、就业材料签署压力大&#xff0c;盖章需求激增&#xff0c;如何快捷、高效地处理各类毕业、就业材料签署问题呢&#xff1f; 在教育部…

间隔损失函数

度量损失&#xff1a; Contrastive Loss 核心含义&#xff1a;同类的样本要更近&#xff0c;不同类的样本要更远 正样本不用管&#xff0c;把负样本分开就行&#xff0c;最小化损失函数就是最大化决策边界和负样本的距离 Triplet Loss Triplet Loss是一种用于训练深度学习中…

7-2 哈利·波特的考试

哈利波特要考试了&#xff0c;他需要你的帮助。这门课学的是用魔咒将一种动物变成另一种动物的本事。例如将猫变成老鼠的魔咒是haha&#xff0c;将老鼠变成鱼的魔咒是hehe等等。反方向变化的魔咒就是简单地将原来的魔咒倒过来念&#xff0c;例如ahah可以将老鼠变成猫。另外&…

git的学习2

文章目录 一、Git 创建仓库二、Git 基本操作1总结 一、Git 创建仓库 git init Git 使用 git init 命令来初始化一个 Git 仓库&#xff0c;Git 的很多命令都需要在 Git 的仓库中运行&#xff0c;所以 git init 是使用 Git 的第一个命令。 在执行完成 git init 命令后&#xf…

Opencascad开发(C#)-建模-反向片体(SheetBody)的法向矢量

文章目录 1、前言2、在UG NX中构建一个片体3、在UG NX中查看片体的法向矢量4、采用UFun函数来实现法向反向5、代码实现6、测试效果1、前言 在UG NX中,一张曲面获取其所属的片体(SheetBody)对象,其在构建时有默认的法向矢量,有时处于功能的需求,比如加工时工件的材料去除方…

根据IP获取地理位置信息 — Golang

根据IP获取地理位置信息 — Golang 1 介绍1.1 ip2region1.2 geoip2-golang1.3 总结 2 使用2.1 ip2region2.2 geoip2-golang 1 介绍 1 ip2region 2 geoip2-golang 1.1 ip2region ip2region 是一个离线IP地址定位库和IP定位数据管理框架&#xff0c;10微秒级别的查询效率&…

ipad密码忘了怎么解锁?教你40秒轻松移除!

无论是手机还是平板&#xff0c;相信大部分都会去给它们设上密码&#xff0c;来保证自己的隐私安全。同理&#xff0c;无论是苹果设备还是安卓设备&#xff0c;一旦设了锁屏密码&#xff0c;就会遇到密码忘记的情况&#xff0c;多次输入错误密码还会导致设备被停用。 近日&…

上海亚商投顾:沪指放量上涨创年内新高 中字头个股掀涨停潮

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 市场情绪 沪指今日高开高走&#xff0c;盘中一度涨近2%&#xff0c;站上3400点关口&#xff0c;深成指、创业板指走势较弱。…

openssl一套证书-配置文件和证书签发

dn-param 和 extend 配置文件 CA的dn-param 和 extend CA的dn-param 和 extend CI-csr.cnf 的内容如下&#xff1a; #openssl x509 extfile params extensions extend # This prevent the user to be prompted for values prompt nodistinguished_name dn-param [dn-param…