互斥锁的概念
1、互斥锁又称互斥型信号量,是一种特殊的二值性信号量,用于实现对共享资源的独占式处理。 2、任意时刻互斥锁的状态只有两种:开锁或闭锁。 3、当有任务持有时,互斥锁处于闭锁状态,这个任务获得该互斥锁的所有权。 4、当该任务释放时,该互斥锁被开锁,任务失去该互斥锁的所有权。 5、当一个任务持有互斥锁时,其他任务将不能再对该互斥锁进行开锁或持有。 6、多任务环境下往往存在多个任务竞争同一共享资源的应用场景,互斥锁可被用于对共享资源的保护从而实现独占式访问。 另外,互斥锁可以解决信号量存在的优先级翻转问题。
运作原理- 多任务环境下会存在多个任务访问同一公共资源的场景,而有些公共资源是非共享的,需要任务进行独占式处理。互斥锁怎样来避免这种冲突呢?
- 用互斥锁处理非共享资源的同步访问时,如果有任务访问该资源,则互斥锁为加锁状态。此时其他任务如果想访问这个公共资源则会被阻塞,直到互斥锁被持有该锁的任务释放后,其他任务才能重新访问该公共资源,此时互斥锁再次上锁,如此确保同一时刻只有一个任务正在访问这个公共资源,保证了公共资源操作的完整性。
- 创建互斥锁: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);
#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 mutex
status = 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);
- 编译烧录运行