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[];
static rt_uint8_t test2_stack[]; /* 静态线程的 线程控制块 */
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.\n"); /* 获得当前的OS Tick */
tick = rt_tick_get();
result = rt_mutex_take(&static_mutex, ); if (result == -RT_ETIMEOUT)
{
/* 超时后判断是否刚好是10个OS Tick */
if (rt_tick_get() - tick != )
{
rt_mutex_detach(&static_mutex);
return;
}
rt_kprintf("thread1 take static mutex timeout\n");
}
else
{
/* 线程2持有互斥量,且在相当长的时间后才会释放互斥量,
* 因此10个tick后线程1不可能获得 */
rt_kprintf("thread1 take a static mutex, failed.\n");
rt_mutex_detach(&static_mutex);
return;
} /* 永久等待方式持有互斥量 */
rt_kprintf("thread1 try to get static mutex, wait forever.\n");
result = rt_mutex_take(&static_mutex, RT_WAITING_FOREVER);
if (result != RT_EOK)
{
/* 不成功则测试失败 */
rt_kprintf("thread1 take a static mutex, failed.\n");
rt_mutex_detach(&static_mutex);
return;
} rt_kprintf("thread1 take a staic mutex, done.\n"); /* 脱离互斥量对象 */
rt_mutex_detach(&static_mutex); /* 2. dynamic mutex test */ /* 试图持有互斥量,最大等待10个OS Tick后返回 */
rt_kprintf("thread1 try to get dynamic mutex, wait 10 ticks.\n"); tick = rt_tick_get();
result = rt_mutex_take(dynamic_mutex, );
if (result == -RT_ETIMEOUT)
{
/* 超时后判断是否刚好是10个OS Tick */
if (rt_tick_get() - tick != )
{
rt_mutex_delete(dynamic_mutex);
return;
}
rt_kprintf("thread1 take dynamic mutex timeout\n");
}
else
{
/* 线程2持有互斥量,且在相当长的时间后才会释放互斥量,
* 因此10个tick后线程1不可能获得 */
rt_kprintf("thread1 take a dynamic mutex, failed.\n");
rt_mutex_delete(dynamic_mutex);
return;
} /* 永久等待方式持有互斥量 */
rt_kprintf("thread1 try to get dynamic mutex, wait forever.\n");
result = rt_mutex_take(dynamic_mutex, RT_WAITING_FOREVER);
if (result != RT_EOK)
{
/* 不成功则测试失败 */
rt_kprintf("thread1 take a dynamic mutex, failed.\n");
rt_mutex_delete(dynamic_mutex);
return;
} rt_kprintf("thread1 take a dynamic mutex, done.\n");
/* 删除互斥量对象 */
rt_mutex_delete(dynamic_mutex); } void test2_thread_entry(void* parameter)
{ /* 1. static mutex test */
rt_kprintf("thread2 try to get static mutex\n");
rt_mutex_take(&static_mutex, );
rt_kprintf("thread2 got static mutex\n");
rt_thread_delay(RT_TICK_PER_SECOND);
rt_kprintf("thread2 release static mutex\n");
rt_mutex_release(&static_mutex); /* 2. dynamic mutex test */
rt_kprintf("thread2 try to get dynamic mutex\n");
rt_mutex_take(dynamic_mutex, );
rt_kprintf("thread2 got dynamic mutex\n");
rt_thread_delay(RT_TICK_PER_SECOND);
rt_kprintf("thread2 release dynamic mutex\n");
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.\n");
return -;
} /* 创建一个动态互斥量 */
dynamic_mutex = rt_mutex_create("dmutex", RT_IPC_FLAG_FIFO);
if (dynamic_mutex == RT_NULL)
{
rt_kprintf("create dynamic mutex failed.\n");
return -;
} /* 创建test1线程 : 优先级 16 ,时间片 5个系统滴答 */
result = rt_thread_init(&test1_thread,
"test1",
test1_thread_entry, RT_NULL,
(rt_uint8_t*)&test1_stack[], sizeof(test1_stack), , ); 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[], sizeof(test2_stack), , ); if (result == RT_EOK)
{
rt_thread_startup(&test2_thread);
}
return ;
}
RT-Thread互斥锁的更多相关文章
- linux thread 互斥锁
#include <stdio.h> #include <stdlib.h> #include <pthread.h> void *threadhandle(voi ...
- 多线程编程之Apue3rd_Chapter11之互斥锁_读写锁_自旋锁
学习了apue3rd的第11章,主要讲的是多线程编程.因为线程共享进程的资源比如堆和全局变量,多线程编程最重要的是,使用各种锁进行线程同步. 线程编程首先要学习的三个函数如下: #include &l ...
- C++ 并发编程之互斥锁和条件变量的性能比较
介绍 本文以最简单生产者消费者模型,通过运行程序,观察该进程的cpu使用率,来对比使用互斥锁 和 互斥锁+条件变量的性能比较. 本例子的生产者消费者模型,1个生产者,5个消费者. 生产者线程往队列里放 ...
- Java多线程系列--“JUC锁”02之 互斥锁ReentrantLock
本章对ReentrantLock包进行基本介绍,这一章主要对ReentrantLock进行概括性的介绍,内容包括:ReentrantLock介绍ReentrantLock函数列表ReentrantLo ...
- 异步与并行~ReaderWriterLockSlim实现的共享锁和互斥锁
返回目录 在System.Threading.Tasks命名空间下,使用ReaderWriterLockSlim对象来实现多线程并发时的锁管理,它比lock来说,性能更好,也并合理,我们都知道lock ...
- c# 多线程 --Mutex(互斥锁)
互斥锁(Mutex) 互斥锁是一个互斥的同步对象,意味着同一时间有且仅有一个线程可以获取它. 互斥锁可适用于一个共享资源每次只能被一个线程访问的情况 函数: //创建一个处于未获取状态的互斥锁 Pub ...
- 互斥锁(Mutex)
互斥锁(Mutex)互斥锁是一个互斥的同步对象,意味着同一时间有且仅有一个线程可以获取它.互斥锁可适用于一个共享资源每次只能被一个线程访问的情况 函数://创建一个处于未获取状态的互斥锁Public ...
- JUC回顾之-可重入的互斥锁ReentrantLock
1.什么是可重锁ReentrantLock? 就是支持重新进入的锁,表示该锁能够支持一个线程对资源的重复加锁. 2.ReentrantLock分为公平锁和非公平锁:区别是在于获取锁的机制上是否公平. ...
- zookeeper实现互斥锁
简单的说,zookeeper就是为了解决集群环境中数据一致性的问题. 举个很简单栗子: 有一个变量A,分别存在于两台服务器中,某个程序需要用到变量A,就随机地访问其中一台服务器并取得变量A的值,对吧? ...
- linux多线程编程之互斥锁
多线程并行运行,共享同一种互斥资源时,需要上互斥锁来运行,主要是用到pthread_mutex_lock函数和pthread_mutex_unlock函数对线程进行上锁和解锁 下面是一个例子: #in ...
随机推荐
- ***Linux文件夹文件创建、删除、改名
Linux删除文件夹命令 linux删除目录很简单,很多人还是习惯用rmdir,不过一旦目录非空,就陷入深深的苦恼之中,现在使用rm -rf命令即可.直接rm就可以了,不过要加两个参数-rf 即:rm ...
- ASP.NET Web API 2 中的属性路由使用(转载)
转载地址:ASP.NET Web API 2 中的属性路由使用
- js打印html中的内容
js打印方法 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www. ...
- 解决Windows和Ubuntu时间不一致的问题
问题原因是使用的时间不一致导致的.win10直接从bios读出来的时间认为就是实际时间,ubuntu认为加上8个小时 后的才是.win10用的rtc ,ubuntu用的utc 在ubuntu16.04 ...
- python联接主流SQL的类库个人收藏
我现在主要是用以下这个类库来分别连接oracle,postgresql,mysql,mssql的. PyMySQL,pymssql,cx_Oracle,psycopg2 收藏 一下.. https:/ ...
- oracle怎么卸载(转)
Oracle Database,又名Oracle RDBMS,或简称Oracle.是甲骨文公司的一款关系数据库管理系统.到目前仍在数据库市场上占有主要份额.劳伦斯·埃里森和他的朋友,之前的同事 Bob ...
- CC2540开发板学习笔记(六)——AD控制(自带温度计)
一.实验目的 将采集的内部温度传感器信息通过串口发送到上位机 二.实验过程 1.寄存器配置 ADCCON1(0XB4)ADC控制寄存器1 BIT7:EOC ADC结束标志位0:AD转换进行中 ...
- 复制表结构和数据SQL语句
select * into 目标表名 from 源表名 insert into 目标表名(fld1, fld2) select fld1, 5 from 源表名 以上两句都是将 源表 的数据插入到 目 ...
- scp 使用
[spark-hadoop@master ~]$ sudo scp /etc/profile spark-hadoop@slave1:/etc spark-hadoop@slave1's passwo ...
- lr参数化——500户并发迭代1次 循环取5条数据
lr参数化——500户并发迭代1次 循环取5条数据 比如vuser1.vuser2.vuser3..........,vuser500 shuju1,shuju2,shuju3,shuju4,shuj ...