HarmonyOS IoT设备内核编程接口-----互斥锁

互斥锁(Metux)主要作用是提供了对多线程共享区域的互斥访问,通过互斥锁可以确保只有一个线程在多线程共享区域执行。

一、互斥锁基本概念:

1、互斥锁又称互斥型信号量,是一种特殊的二值性信号量【二值型信号量可以理解为任务与中断间或者两个任务间的标志,该标志非“满”即“空”】,用于实现对共享资源的独占式处理。
2、任意时刻互斥锁的状态只有两种:开锁或闭锁。
3、当有任务持有时,互斥锁处于闭锁状态,这个任务获得该互斥锁的所有权。
4、当该任务释放时,该互斥锁被开锁,任务失去该互斥锁的所有权。
5、当一个任务持有互斥锁时,其他任务将不能再对该互斥锁进行开锁或持有。
6、多任务环境下往往存在多个任务竞争同一共享资源的应用场景,互斥锁可被用于对共享资源的保护从而实现独占式访问。另外,互斥锁可以解决信号量存在的优先级翻转问题。
简单的来说:就是同一时刻,同一资源,只能被同一任务共享;

二、LiteOS提供的互斥锁具有如下特点:

通过优先级继承算法,解决优先级翻转问题。

三、cmsis_os2的API互斥锁(Mutex)接口简介

struct osMutexAttr_t //互斥锁的属性结构体

宏定义:
#define osMutexRecursive 0x00000001U //递归互斥锁

#define osMutexPrioInherit 0x00000002U //优先级继承协议

#define osMutexRobust 0x00000008U //强健的互斥锁

函数:
osMutexId_t osMutexNew (const osMutexAttr_t *attr) //创建并初始化一个互斥锁对象。

const char * osMutexGetName (osMutexId_t mutex_id) //获取互斥锁对象的名称。

osStatus_t osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout) //如果它被锁定,则获取互斥锁或超时值。

osStatus_t osMutexRelease (osMutexId_t mutex_id) //释放由 osMutexAcquire 获取的互斥锁。

osThreadId_t osMutexGetOwner (osMutexId_t mutex_id) //获取拥有互斥锁对象的线程。

osStatus_t osMutexDelete (osMutexId_t mutex_id) //删除互斥锁对象。

互斥锁作用:相互排斥(广为人知的互斥锁)在各种操作系统中用于资源管理。

单片机器件中的许多资源可以重复使用,但一次只能使用一个线程(例如通信通道,内存和文件)。

互斥锁用于保护对共享资源的访问。互斥体被创建并在线程之间传递(它们可以获取并释放互斥锁)

不能从中断服务程序(ISR)调用互斥锁管理函数,这与可以从 ISR 释放的二进制信号不同。有关 RTX5 配置选项,请参阅互斥锁配置。

同一个线程可以多次使用互斥锁,而不会自行锁定。每当拥有的线程获取互斥锁时,锁定计数就会增加。互斥锁必须多次释放,

直到锁计数达到零。在达到零时,互斥锁实际上被释放并且可以被其他线程获取。

四、案例代码

#include <stdio.h>
#include <stdlib.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
//打印测试信息
#define RTOSV2_PRINTF(fmat,...)\
do{\
    printf("RTOSV2.0_TEST:");\
    printf(fmat,##__VA_ARGS__);\
    printf("\r\n");\
}while(0)

//创建子线程
osThreadId_t newThread(char *name,osThreadFunc_t func,void *arg){
    osThreadAttr_t attr = {name, 0, NULL, 0, NULL, 1024*2, osPriorityNormal, 0, 0};
    osThreadId_t tid = osThreadNew(func,arg,&attr);
    if (tid==NULL)
    {
        RTOSV2_PRINTF("osThreadNew(%s) failed.",name);
    }else{
        RTOSV2_PRINTF("osThreadNew(%s) success,thread id:%d.",name,tid);
    }
    return tid;
}

static int g_test_value = 0;
//多线程共享执行函数,操作全局变量+1,并判断奇偶性
void number_thread(void* arg){
    osMutexId_t *mid = (osMutexId_t *) arg;
    while(1)
    {
        if (osMutexAcquire(*mid,100) == osOK){
            g_test_value++;
            if(g_test_value%2==0){
                RTOSV2_PRINTF("%s gets an even value %d",osThreadGetName(osThreadGetId()),g_test_value);
            }else{
                RTOSV2_PRINTF("%s gets an odd value %d",osThreadGetName(osThreadGetId()),g_test_value);
            }
            osMutexRelease(*mid);
            osDelay(5);
        }
    }
}
//创建创建3个子线程,并创建一个互斥锁来控制各个子线程
void rtosv2_mutex_main(void* arg){
    (void) arg;
    osMutexAttr_t attr={0};
    //创建互斥锁
    osMutexId_t mid = osMutexNew(&attr);
    if(mid == NULL){
        RTOSV2_PRINTF("osMutexNew,creat mutex faild.");
    }else{
        RTOSV2_PRINTF("osMutexNew,creat mutex success.");
    }
    //调用子线程创建函数
    osThreadId_t tid1 = newThread("Thread_1",number_thread,&mid);
    osThreadId_t tid2 = newThread("Thread_2",number_thread,&mid);
    osThreadId_t tid3 = newThread("Thread_3",number_thread,&mid);

    osDelay(13);
    //获得指定互斥锁的所有者线程
    osThreadId_t tid = osMutexGetOwner(mid);
    RTOSV2_PRINTF("osMutexGetowne,thread id:%p,thread name:%s.",tid,osThreadGetName(tid));
    osDelay(17);
    //终止指定线程
    osThreadTerminate(tid1);
    osThreadTerminate(tid2);
    osThreadTerminate(tid3);
    //删除指定互斥锁
    osMutexDelete(mid);
}
//主线程
void MutexEntry(void){
    osThreadAttr_t attr;
    attr.name = "rtosv2_mutex_main";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 10240;
    attr.priority = osPriorityNormal;

    if (osThreadNew(rtosv2_mutex_main, NULL, &attr) == NULL) {
        printf("[mutex_demo] Falied to create rtosv2_mutex_main!\n");
    }
}
SYS_RUN(MutexEntry);

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值