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