Bearpi开发板之HarmonyOS互斥锁
互斥锁的概念
1、互斥锁又称互斥型信号量,是一种特殊的二值性信号量,用于实现对共享资源的独占式处理。
2、任意时刻互斥锁的状态只有两种:开锁或闭锁。
3、当有任务持有时,互斥锁处于闭锁状态,这个任务获得该互斥锁的所有权。
4、当该任务释放时,该互斥锁被开锁,任务失去该互斥锁的所有权。
5、当一个任务持有互斥锁时,其他任务将不能再对该互斥锁进行开锁或持有。
6、多任务环境下往往存在多个任务竞争同一共享资源的应用场景,互斥锁可被用于对共享资源的保护从而实现独占式访问。
另外,互斥锁可以解决信号量存在的优先级翻转问题。
运作原理
- 多任务环境下会存在多个任务访问同一公共资源的场景,而有些公共资源是非共享的,需要任务进行独占式处理。互斥锁怎样来避免这种冲突呢?
- 用互斥锁处理非共享资源的同步访问时,如果有任务访问该资源,则互斥锁为加锁状态。此时其他任务如果想访问这个公共资源则会被阻塞,直到互斥锁被持有该锁的任务释放后,其他任务才能重新访问该公共资源,此时互斥锁再次上锁,如此确保同一时刻只有一个任务正在访问这个公共资源,保证了公共资源操作的完整性。
cmsis_os2的API互斥锁接口简介
- 创建互斥锁:osMutexId_t osMutexNew (const osMutexAttr_t *attr);
- 获取互斥锁:osStatus_t osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout);
- 释放互斥锁:osStatus_t osMutexRelease (osMutexId_t mutex_id);
- 删除互斥锁:osStatus_t osMutexDelete (osMutexId_t mutex_id);
创建高中低优先级共3个任务和一个互斥对象
#include #include #include "ohos_init.h"#include #include "cmsis_os2.h"#include "wifiiot_gpio.h"#include "wifiiot_gpio_ex.h"void hi_thread(void *p){ osDelay(100); while(1) { osMutexAcquire(p,osWaitForever); printf("hi thread\n"); osDelay(300); osMutexRelease(p); }}void mid_thread(void *p){ (void)p; osDelay(100); while(1) { printf("mid thread\n"); osDelay(100); }}void low_thread(void *p){ while(1) { osMutexAcquire(p,osWaitForever); printf("low thread\n"); osDelay(300); osMutexRelease(p); }}void my_led_example(void){ GpioInit(); IoSetFunc(WIFI_IOT_IO_NAME_GPIO_2,WIFI_IOT_IO_FUNC_GPIO_2_GPIO); GpioSetDir(WIFI_IOT_IO_NAME_GPIO_2,WIFI_IOT_GPIO_DIR_OUT); osThreadAttr_t attr; attr.attr_bits = 0; attr.cb_mem = NULL; attr.cb_size = 0; attr.stack_mem = NULL; attr.stack_size = 1024; attr.priority = 25; static osMutexId_t mutex; mutex = osMutexNew(NULL); if (mutex == NULL) {printf("Falied to create mutex!\n"); } osThreadId_t id = osThreadNew(hi_thread,mutex,&attr); if(id == NULL) { printf("Falied to create hi_thread!\n"); } attr.priority = 24; id = osThreadNew(mid_thread,mutex,&attr); if(id == NULL) { printf("Falied to create mid_thread!\n"); } attr.priority = 23; id = osThreadNew(low_thread,mutex,&attr); if(id == NULL) { printf("Falied to create low_thread!\n"); }}SYS_RUN(my_led_example);
- 编译烧录运行
扩展实验代码
#include #include #include "ohos_init.h"#include #include "cmsis_os2.h"#include "wifiiot_gpio.h"#include "wifiiot_gpio_ex.h"void hi_thread(void *p){ osDelay(100U); osStatus_t status; while (1) { // try to acquire mutexstatus = osMutexAcquire(p, osWaitForever); printf("hi_thread is runing.\r\n"); if(status != osOK) { printf("hi thread acquire mutex failed\r\n"); } else { printf("hi thread acquire mutex success\r\n"); } printf("hi thread block 3s\n"); osDelay(300U); printf("hi thread osMutexRelease is called\n"); status = osMutexRelease(p); if(status != osOK) { printf("hi thread release mutex failed\r\n"); } else { printf("hi thread release mutex success\r\n"); } }}void mid_thread(void *p){ (void)p; osDelay(100); while(1) { printf("mid thread\n"); osDelay(100); }}void low_thread(void *p){ osStatus_t status; while (1) { status = osMutexAcquire(p, osWaitForever); printf("low_thread is runing.\r\n"); if(status != osOK) { printf("lo tread acquire mutex failed\r\n"); } else {printf("lo thread acquire mutex success\r\n"); } // block mutex for 3s printf("lo thread block 3s\n"); osDelay(300U); printf("lo thread osMutexRelease is called\n"); status = osMutexRelease(p); if(status != osOK) { printf("lo thread release mutex failed\r\n"); } else { printf("lo thread release mutex success\r\n"); } }}void my_led_example(void){ GpioInit(); IoSetFunc(WIFI_IOT_IO_NAME_GPIO_2,WIFI_IOT_IO_FUNC_GPIO_2_GPIO); GpioSetDir(WIFI_IOT_IO_NAME_GPIO_2,WIFI_IOT_GPIO_DIR_OUT); osThreadAttr_t attr; attr.attr_bits = 0; attr.cb_mem = NULL; attr.cb_size = 0; attr.stack_mem = NULL; attr.stack_size = 1024; attr.priority = 25; static osMutexId_t mutex; mutex = osMutexNew(NULL); if (mutex == NULL) {printf("Falied to create mutex!\n"); } osThreadId_t id = osThreadNew(hi_thread,mutex,&attr); if(id == NULL) { printf("Falied to create hi_thread!\n"); } attr.priority = 24; id = osThreadNew(mid_thread,mutex,&attr); if(id == NULL) { printf("Falied to create mid_thread!\n"); } attr.priority = 23; id = osThreadNew(low_thread,mutex,&attr); if(id == NULL) { printf("Falied to create low_thread!\n"); }}SYS_RUN(my_led_example);
- 编译烧录运行