RT-Thread互斥锁

互斥锁和信号量很相似, RT-Thread 中的互斥锁也有静态和动态之分,和互斥锁有关的
操作如下:
初始化—rt_mutex_init()(对应静态互斥锁);
建立—rt_mutex_create()(对应动态互斥锁);
获取—rt_mutex_take();
释放—rt_ mutex_release();
脱离—rt_mutex_detach()( 对应静态信号量) ;
删除—rt_mutex_delete()( 对应动态信号量);

我们看到信号量和互斥锁如此形似,那么它们的区别在哪里?我以我的理解,区别一下这两个 IPC 对象:

1、信号量哪里都可以释放,但互斥锁只有获得了其控制权的线程才可以释放,即:只有“锁上”它的那个线程才有“钥匙”打开它,有“所有权”的概念。


2、信号量可能导致线程优先级反转,而互斥锁可通过优先级继承的方法解决优先级反转问题(详见《 RT-Thread 编程指南》) 。

    实际中我们常遇到这样的情况,比如一个总线上挂接着 N 个设备,这是我们必须“分时”的去操作各个设备,这时候互斥锁就派上用场了:我们在开始操作某个设备前先使用
rt_mutex_take ()锁住总线,然后开始对设备的具体操作,最后通过 rt_mutex_release (),解锁总线,让给其他设备去使用。


   信号量用于同步的时候就像交通灯,任务只有在获得许可的时候才可以运行,强调的是运行步骤;信号量用于互斥的时候就像一把钥匙,它强调只有获得钥匙的任务才可以运行,
强调的是许可和权限。这两者都不具备任何数据交换的功能,下面来介绍具有数据交换功能的 IPC 对象: 邮箱和消息队列。

/**********************************************************************************************************
*
*    模块名称 : 功能演示
*    文件名称 : test.c
*    版    本 : V1.0
*    说    明 :
*    修改记录 :
*        版本号  日期        作者                        说明
*
*        v1.0    2013-4-20   jiezhi320(UP MCU 工作室)    演示互斥锁的基本使用
*
*    Copyright (C), 2012-2013,
*   淘宝店:   http://shop73275611.taobao.com
*   QQ交流群: 258043068
*
**********************************************************************************************************/
#include <rtthread.h>
#include <stm32f10x.h>
#include "test.h"


/*  变量分配4字节对齐 */
ALIGN(RT_ALIGN_SIZE)

/*  静态线程的 线程堆栈*/
static rt_uint8_t test1_stack[512];
static rt_uint8_t test2_stack[512];

/* 静态线程的 线程控制块 */
static struct rt_thread test1_thread;
static struct rt_thread test2_thread;

/* 互斥量控制块 */
static struct rt_mutex static_mutex;
/* 指向互斥量的指针 */
static rt_mutex_t dynamic_mutex = RT_NULL;


void test1_thread_entry(void* parameter)
{
    rt_err_t result;
    rt_tick_t tick;

    /* 1. staic mutex demo */

    /* 试图持有互斥量,最大等待10个OS Tick后返回 */
    rt_kprintf("thread1 try to get static mutex, wait 10 ticks.
");

    /* 获得当前的OS Tick */
    tick = rt_tick_get();
    result = rt_mutex_take(&static_mutex, 10);

    if (result == -RT_ETIMEOUT)
    {
        /* 超时后判断是否刚好是10个OS Tick */
        if (rt_tick_get() - tick != 10)
        {
            rt_mutex_detach(&static_mutex);
            return;
        }
        rt_kprintf("thread1 take static mutex timeout
");
    }
    else
    {
        /* 线程2持有互斥量,且在相当长的时间后才会释放互斥量,
         * 因此10个tick后线程1不可能获得 */
        rt_kprintf("thread1 take a static mutex, failed.
");
        rt_mutex_detach(&static_mutex);
        return;
    }

    /* 永久等待方式持有互斥量 */
    rt_kprintf("thread1 try to get static mutex, wait forever.
");
    result = rt_mutex_take(&static_mutex, RT_WAITING_FOREVER);
    if (result != RT_EOK)
    {
        /* 不成功则测试失败 */
        rt_kprintf("thread1 take a static mutex, failed.
");
        rt_mutex_detach(&static_mutex);
        return;
    }

    rt_kprintf("thread1 take a staic mutex, done.
");

    /* 脱离互斥量对象 */
    rt_mutex_detach(&static_mutex);

    /* 2. dynamic mutex test */

    /* 试图持有互斥量,最大等待10个OS Tick后返回 */
    rt_kprintf("thread1 try to get dynamic mutex, wait 10 ticks.
");

    tick = rt_tick_get();
    result = rt_mutex_take(dynamic_mutex, 10);
    if (result == -RT_ETIMEOUT)
    {
        /* 超时后判断是否刚好是10个OS Tick */
        if (rt_tick_get() - tick != 10)
        {
            rt_mutex_delete(dynamic_mutex);
            return;
        }
        rt_kprintf("thread1 take dynamic mutex timeout
");
    }
    else
    {
        /* 线程2持有互斥量,且在相当长的时间后才会释放互斥量,
         * 因此10个tick后线程1不可能获得 */
        rt_kprintf("thread1 take a dynamic mutex, failed.
");
        rt_mutex_delete(dynamic_mutex);
        return;
    }

    /* 永久等待方式持有互斥量 */
    rt_kprintf("thread1 try to get dynamic mutex, wait forever.
");
    result = rt_mutex_take(dynamic_mutex, RT_WAITING_FOREVER);
    if (result != RT_EOK)
    {
        /* 不成功则测试失败 */
        rt_kprintf("thread1 take a dynamic mutex, failed.
");
        rt_mutex_delete(dynamic_mutex);
        return;
    }

    rt_kprintf("thread1 take a dynamic mutex, done.
");
    /* 删除互斥量对象 */
    rt_mutex_delete(dynamic_mutex);

}


void test2_thread_entry(void* parameter)
{

    /* 1. static mutex test */
    rt_kprintf("thread2 try to get static mutex
");
    rt_mutex_take(&static_mutex, 10);
    rt_kprintf("thread2 got static mutex
");
    rt_thread_delay(RT_TICK_PER_SECOND);
    rt_kprintf("thread2 release static mutex
");
    rt_mutex_release(&static_mutex);

    /* 2. dynamic mutex test */
    rt_kprintf("thread2 try to get dynamic mutex
");
    rt_mutex_take(dynamic_mutex, 10);
    rt_kprintf("thread2 got dynamic mutex
");
    rt_thread_delay(RT_TICK_PER_SECOND);
    rt_kprintf("thread2 release dynamic mutex
");
    rt_mutex_release(dynamic_mutex);

}

rt_err_t demo_thread_creat(void)
{
    rt_err_t result;

    /* 初始化静态互斥量 */
    result = rt_mutex_init(&static_mutex, "smutex", RT_IPC_FLAG_FIFO);
    if (result != RT_EOK)
    {
        rt_kprintf("init static mutex failed.
");
        return -1;
    }

    /* 创建一个动态互斥量 */
    dynamic_mutex = rt_mutex_create("dmutex", RT_IPC_FLAG_FIFO);
    if (dynamic_mutex == RT_NULL)
    {
        rt_kprintf("create dynamic mutex failed.
");
        return -1;
    }


    /* 创建test1线程 : 优先级 16 ,时间片 5个系统滴答 */
    result = rt_thread_init(&test1_thread,
                            "test1",
                            test1_thread_entry, RT_NULL,
                            (rt_uint8_t*)&test1_stack[0], sizeof(test1_stack), 16, 5);

    if (result == RT_EOK)
    {
        rt_thread_startup(&test1_thread);
    }

    /* 创建test2线程 : 优先级 15 ,时间片 5个系统滴答 */
    result = rt_thread_init(&test2_thread,
                            "test2",
                            test2_thread_entry, RT_NULL,
                            (rt_uint8_t*)&test2_stack[0], sizeof(test2_stack), 15, 5);

    if (result == RT_EOK)
    {
        rt_thread_startup(&test2_thread);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/yygsj/p/5519293.html