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 ...
随机推荐
- Windows Phone8 遇见的问题
1.公司的无线路由可以自动分发ip地址,模拟器可以自动获取ip,进行连接.宿舍的无线路设置了DHCP 不能自动分发ip地址,模拟器连接不到ip,上不去网,我就去hyper-v 管理器里修改了静态mac ...
- ThinkPHP的增、删、改、查
一.创建操作 在ThinkPHP使用add方法新增数据到数据库. 使用方法如下: $User = M()->; $data[););')->delete();
- 我对序列化(Serializable)的理解
转自:http://blog.tianya.cn/blogger/post_show.asp?BlogID=764&PostID=3231409 序列化是把一个对象的状态写入一个字节流的过程. ...
- 解决:Google代码achartengine曲线代码报错问题(转)
原文地址链接 官网:http://code.google.com/p/achartengine/ 下载代码部署项目会报下面的错误: java.lang.NoClassDefFoundError: or ...
- Session: 防止用户多次登陆
在web开发时,有的系统要求同一个用户在同一时间只能登录一次,也就是如果一个用户已经登录了,在退出之前如果再次登录的话需要报错. 常见的处理方法是,在用户登录时,判断此用户是否已经在Applicati ...
- Web测试Selenium:如何选取元素
Web测试工具Selenium:如何选取元素 2009-02-17 23:23 by 敏捷的水, 5372 阅读, 22 评论, 收藏, 编辑 selenium是一个非常棒的Web测试工具,他对Aja ...
- xcode命令行编译时:codesign命令,抛出“User interaction is not allowed.”异常 的处理
之前正常运行的hudson iOS编译服务器slave节点,忽然出现编译失败.发现原因有2个: 第一个原因是编译机上用来签名的用户帐号过期,第二个原因是操作系统和xCode升级造成的. 对于第一个,重 ...
- vs 数据库链接Web.config 配置
1.使用Windows身份验证 <add name="SQLConnectionString" connectionString="Data Source=U5MJ ...
- spring实战三装配bean之Bean的作用域以及初始化和销毁Bean
1.Bean的作用域 所有的spring bean默认都是单例.当容器分配一个Bean时,不论是通过装配还是调用容器的getBean()方法,它总是返回Bean的同一个实例.有时候需要每次请求时都获得 ...
- 位运算 ZOJ 3870 Team Formation
题目传送门 /* 题意:找出符合 A^B > max (A, B) 的组数: 位运算:异或的性质,1^1=0, 1^0=1, 0^1=1, 0^0=0:与的性质:1^1=1, 1^0=0, 0^ ...