【FreeRTOS】互斥锁的使用

简介: 【FreeRTOS】互斥锁的使用

创建、删除

互斥量是一种特殊的二进制信号量,使用互斥量时,先创建、然后去获得、释放它。使用句柄来表示一个互斥量。

SemaphoreHandle_t xSemaphoreCreateMutex( void );

返回值: 返回句柄,非NULL表示成功

void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );

SemaphoreHandle_t xSemaphore:,这里直接传入mutex就可以删除

上锁、开锁

上锁

BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore );

SemaphoreHandle_t xSemaphore:信号量句柄,释放哪个信号量

返回值 :pdTRUE表示成功,如果二进制信号量的计数值已经是1,再次调用此函数则返回失败;

如果计数型信号量的计数值已经是最大值,再次调用此函数则返回失败;

开锁

BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore,
                        TickType_t xTicksToWait);

SemaphoreHandle_t xSemaphore:信号量句柄,释放哪个信号量

TickType_t xTicksToWait:如果无法马上获得信号量,阻塞一会:

  1. 0:不阻塞,马上返回
  2. portMAX_DELAY: 一直阻塞直到成功,
  3. 其他值: 阻塞的Tick个数,可以使用pdMS_TO_TICKS()来指定阻塞时间为若干ms;

返回值 :pdTRUE表示成功

可以看到互斥量的api和信号量的api是一样的,因为互斥量的本质是一个特殊信号量,但是需要注意互斥量不能在ISR中使用;

示例

互斥量的使用场景一般是在多个任务中操作同一个变量的时候会出现使用;下面我们先创建一个三个任务同时操作一个变量的示例;

xTaskCreate((TaskFunction_t )AppTask1,      /* 任务入口函数 */
              (const char*    )"AppTask1",      /* 任务名字 */
              (uint16_t       )128,       /* 任务栈大小 */
              (void*          )NULL,      /* 任务入口函数参数 */
              (UBaseType_t    )1,         /* 任务的优先级 */
               NULL);                         /* 任务控制块指针 */ 
              
              
    xTaskCreate((TaskFunction_t )AppTask2,      /* 任务入口函数 */
              (const char*    )"AppTask2",    /* 任务名字 */
              (uint16_t       )128,       /* 任务栈大小 */
              (void*          )NULL,      /* 任务入口函数参数 */
              (UBaseType_t    )1,         /* 任务的优先级 */
               NULL);                         /* 任务控制块指针 */ 
              
    xTaskCreate((TaskFunction_t )AppTask3,      /* 任务入口函数 */
              (const char*    )"AppTask3",    /* 任务名字 */
              (uint16_t       )128,       /* 任务栈大小 */
              (void*          )NULL,      /* 任务入口函数参数 */
              (UBaseType_t    )1,         /* 任务的优先级 */
               NULL);  
uint32_t count = 0;
static void AppTask1(void *par)
{
    while(1)
    {
        printf("task1 print count = %d\r\n", count++);
    }
}
static void AppTask2(void *par)
{
    while(1)
    {
        printf("task2 print count = %d\r\n", count++);
        
        xSemaphoreGive( xMutex );       /* 给出互斥量 */
    }
}
static void AppTask3(void *par)
{
    while(1)
    {
        printf("task3 print count = %d\r\n", count++);
    }
}

可以看到我们每个任务获取数值都跳跃了非常多的数值,因为这三个任务都是同一优先级所以我们的系统调度会不断的在这三个任务中切换,如果任务刚好处在count++的位置这时候就切换到另外一个线程的count++的位置然而执行自加的这个过程系统调度可以执行上百次最后到打印的位置我们的值已经被其他任务操作了很多次了,所以中间的很多值没有打印出来就直接打印200多这个数值,如果我们加上线程锁,那我们的线程获取到锁过后此时其他两个线程将会一直等待获取到锁的任务操作完发送了释放信号才能拿到锁才能继续操作,那我们上述的任务切换就不会再出现了;

uint32_t count = 0;
SemaphoreHandle_t xMutex;
#define MUTEX 1
static void AppTask1(void *par)
{
    while(1)
    {
        #if MUTEX
        xSemaphoreTake(xMutex,          /* 互斥量句柄 */
                       portMAX_DELAY);  /* 等待时间 */
        #endif
        
        printf("task1 print count = %d\r\n", count++);
        
        #if MUTEX
        xSemaphoreGive( xMutex );       /* 给出互斥量 */
        #endif
    }
}
static void AppTask2(void *par)
{
    while(1)
    {
        #if MUTEX
        xSemaphoreTake(xMutex,          /* 互斥量句柄 */
                       portMAX_DELAY);  /* 等待时间 */
        #endif
        
        printf("task2 print count = %d\r\n", count++);
        
        #if MUTEX
        xSemaphoreGive( xMutex );       /* 给出互斥量 */
        #endif
    }
}
static void AppTask3(void *par)
{
    while(1)
    {
        #if MUTEX
        xSemaphoreTake(xMutex,          /* 互斥量句柄 */
                       portMAX_DELAY);  /* 等待时间 */
        #endif
        
        printf("task3 print count = %d\r\n", count++);
        
        #if MUTEX
        xSemaphoreGive( xMutex );       /* 给出互斥量 */
        #endif
    }
}
#if MUTEX
  xMutex = xSemaphoreCreateMutex();
  #endif
    
    xTaskCreate((TaskFunction_t )AppTask1,      /* 任务入口函数 */
              (const char*    )"AppTask1",      /* 任务名字 */
              (uint16_t       )128,       /* 任务栈大小 */
              (void*          )NULL,      /* 任务入口函数参数 */
              (UBaseType_t    )1,         /* 任务的优先级 */
               NULL);                         /* 任务控制块指针 */ 
              
              
    xTaskCreate((TaskFunction_t )AppTask2,      /* 任务入口函数 */
              (const char*    )"AppTask2",    /* 任务名字 */
              (uint16_t       )128,       /* 任务栈大小 */
              (void*          )NULL,      /* 任务入口函数参数 */
              (UBaseType_t    )1,         /* 任务的优先级 */
               NULL);                         /* 任务控制块指针 */ 
              
    xTaskCreate((TaskFunction_t )AppTask3,      /* 任务入口函数 */
              (const char*    )"AppTask3",    /* 任务名字 */
              (uint16_t       )128,       /* 任务栈大小 */
              (void*          )NULL,      /* 任务入口函数参数 */
              (UBaseType_t    )1,         /* 任务的优先级 */
               NULL); 

结尾

我是凉开水白菜,我们下文见~


相关文章
|
5天前
|
Linux 程序员 API
POSIX互斥锁自旋锁
POSIX互斥锁自旋锁
45 0
|
5天前
|
API 调度
【FreeRTOS】信号量的使用
【FreeRTOS】信号量的使用
|
5天前
|
Linux 调度 C语言
【Linux C/C++ 线程同步 】Linux互斥锁和条件变量:互斥锁和条件变量在Linux线程同步中的编程实践
【Linux C/C++ 线程同步 】Linux互斥锁和条件变量:互斥锁和条件变量在Linux线程同步中的编程实践
48 0
|
5天前
|
Linux
Linux多线程中互斥锁、读写锁、自旋锁、条件变量、信号量详解
Linux多线程中互斥锁、读写锁、自旋锁、条件变量、信号量详解
78 0
Linux多线程中互斥锁、读写锁、自旋锁、条件变量、信号量详解
|
11月前
|
存储 缓存 安全
Linux下线程同步(带你了解什么是互斥锁、死锁、读写锁、条件变量、信号量等)
Linux下线程同步(带你了解什么是互斥锁、死锁、读写锁、条件变量、信号量等)
132 0
|
存储 网络协议 API
4-FreeRTOS队列、互斥、信号量
4-FreeRTOS队列、互斥、信号量
|
Linux
一文读懂Linux多线程中互斥锁、读写锁、自旋锁、条件变量、信号量
Hello、Hello大家好,我是木荣,今天我们继续来聊一聊Linux中多线程编程中的重要知识点,详细谈谈多线程中同步和互斥机制。
8491 1
一文读懂Linux多线程中互斥锁、读写锁、自旋锁、条件变量、信号量
|
Linux
【Linux线程同步专题】三、条件变量
【Linux线程同步专题】三、条件变量
107 0
|
安全 调度 数据库
Windows开发——临界区,互斥量,信号量,事件的简单介绍与区别
Windows开发——临界区,互斥量,信号量,事件的简单介绍与区别
498 0