• 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;
    }
  • 相关阅读:
    20175310 《Java程序设计》第3周学习总结
    IDEA学生免费申请教程
    20175310 《Java程序设计》第2周学习总结
    在虚拟机中使用中文输入法
    VMware虚拟机将英文改成中文的方法
    20175310 《Java程序设计》第1周学习总结(1)安装虚拟机
    20175310 《Java程序设计》第1周学习总结(2)
    Java 开源 CMS :magnolia
    开源网络监控管理系统:OpenNMS
    开源摄影机:Axiom Camera
  • 原文地址:https://www.cnblogs.com/yygsj/p/5519293.html
Copyright © 2020-2023  润新知