RT-Thread多线程导致的临界区问题
界区( Critical Section),每次只准许一个线程进入临界区,进入后不允许其他线程进入。多线程程序的开发方式不同于裸机程序,多个线程在宏观上是并发运行的,因此使用一个共享资源是需要注意,否则就可能出现错误的运行结果。
#include <rtthread.h>
#include <stm32f10x.h>
#include "test.h" rt_uint32_t g_tmp;/* 定义一个全局变量*/ /* 变量分配4字节对齐 */
ALIGN(RT_ALIGN_SIZE) /* 静态线程的 线程堆栈*/
static rt_uint8_t thread1_stack[];
static rt_uint8_t thread2_stack[]; /* 静态线程的 线程控制块 */
static struct rt_thread thread_test1;
static struct rt_thread thread_test2; static void test1_thread_entry(void* parameter);
static void test2_thread_entry(void* parameter); void demo_thread_creat(void)
{
rt_err_t result; /* 创建静态线程 : 优先级 15 ,时间片 2个系统滴答 */
result = rt_thread_init(&thread_test1,
"test1",
test1_thread_entry, RT_NULL,
(rt_uint8_t*)&thread1_stack[], sizeof(thread1_stack), , ); if (result == RT_EOK)
{
rt_thread_startup(&thread_test1);
} /* 创建静态线程 : 优先级 16 ,时间片 1个系统滴答 */
result = rt_thread_init(&thread_test2,
"test2",
test2_thread_entry, RT_NULL,
(rt_uint8_t*)&thread2_stack[], sizeof(thread2_stack), , ); if (result == RT_EOK)
{
rt_thread_startup(&thread_test2);
} } void test1_thread_entry(void* parameter)
{
rt_uint32_t i; g_tmp = ;
rt_kprintf("g_tmp=:%d \r\n", g_tmp);
for(i=; i<; i++)
{
g_tmp++;
}
rt_kprintf("g_tmp=:%d \r\n", g_tmp);
} void test2_thread_entry(void* parameter)
{
rt_thread_delay();// 1 rt_thread_delay(100);两种情况下得到两张图片 g_tmp++;
}

结果分析:
在 test1 线程的 for 循环中我们对 i 做了 10000 次累加,如果没有其他线程的“干预”,那么全局变量 g_tmp 的值应该是 10000,现在的输出结果是 10001,这意味全局变量 g_tmp 的值被线程 2 修改过。整个程序运行过程中各个线程的状态变化是这样的: rt_application_init 中创建两个线程之后,由于 test2 线程的优先级比 test1 线程的优先级高,因此 test2 线程先运行,其线程处理函数第一句为 rt_thread_delay(1), 这会使得 test2 线程被挂起,挂起时间为 1 个时间片,在 test2 线程挂起的这段时间中, test1 线程是所有就绪态线程中优先级最高的线程,因此被内核调度运行。 在 test1 线程执行了一部分代码后, 1 个 tick 时间到, test2 线程被唤醒,从而成为所有就绪线程中优先级最高的线程,因此会被立刻调度运行, test1 线程被 test2 线程抢占, test2 线程中对全局变量 g_tmp 做累加操作,接下来 test2 线程执行完毕, test1 线程再次被调度运行,根据程序的运行结果可以看出,此时 test1 线程继续执行,但是我们并不知道此时 test1 线程大致是从什么地方在开始执行的,从最后的输出结果来看,只能得知此时test1 线程还没有执行到第二条 rt_kprintf 输出语句。最后 test1 线程再次打印全局变量 g_tmp的值,其值就应该是 10001。当 test2线程中的第一句为 rt_thread_delay(100)的时候,在 test2线程休眠的整个时间里,test1 线程都已经执行完毕,因此最后的输出结果为 10000。
从以上可以看到: 当公共资源在多个线程中公用时,如果缺乏必要的保护错误,最后的输出结果可能与预期的结果完全不同。为了解决这种问题,需要引入线程间通信机制,这就
是所谓的 IPC 机制( Inter-Process Communication)。
RT-Thread多线程导致的临界区问题的更多相关文章
- PowerBuilder编程新思维2:嵌入(Thread多线程)
PowerBuilder编程新思维2:嵌入(Thread多线程) 在PB中使用多线程,在网上有大量的文章介绍.不过深入研究并试着给出更易用的模型的,目前还只有"路人甲cw"的一篇& ...
- RT Thread 通过ENV来配置SFUD,操作SPI Flash
本实验基于正点原子stm32f4探索者板子 请移步我的RT Thread论坛帖子. https://www.rt-thread.org/qa/forum.php?mod=viewthread& ...
- Boost::Thread 多线程的基础知识
Boost.Thread可以使用多线程执行可移植C++代码中的共享数据.它提供了一些类和函数来管理线程本身,还有其它一些为了实现在线程之间同步数据或者提供针对特定单个线程的数据拷贝.头文件:#incl ...
- C++多线程同步之临界区(CriticalSection)
原文链接:http://blog.csdn.net/olansefengye1/article/details/53262917 一.Win32平台 1.相关头文件和接口 #include <w ...
- .NET进阶篇06-async异步、thread多线程1
知识需要不断积累.总结和沉淀,思考和写作是成长的催化剂 异步多线程挺大一块内容,既想拆开慢慢学,又想一股脑全倒出.纠结再三,还是拆开吃透,也不至于篇幅过长,劝退许多人 本篇先做一个概述,列明一些基本概 ...
- JUC学习笔记--Thread多线程基础
实现多线程的两种方法 java 实现多线程通过两种方式1.继承Thread类 ,2.实现Runnable接口 class Newthead extends Thread{ public void ru ...
- Thread多线程(一)
网上关于多线程的讲解有很多,意义也不用过多介绍,相信聪明的你早已知道,下面我们在剖析一下JAVA中的多线程的一些方法. 在JAVA中分别提供了两种方式实现多线程,分别继承Java.lang.Threa ...
- 由《win32多线程程序设计》临界区的问题所想
之前看侯捷翻译的<win32多线程程序设计>中关于线程同步中的临界区问题,其中举得例子是对链表的操作.死锁的问题是对一个Swaplist函数的问题,现列举代码如下: void SwapLi ...
- 新手浅谈Task异步编程和Thread多线程编程
初学Task的时候上网搜索,看到很多文章的标题都是task取代thread等等相关,我也一直以为task和thread是一类,其实task是.net4.0提出的异步编程,在之前.net1.0有dele ...
随机推荐
- MVC学习笔记---MVC导出excel(数据量大,非常耗时的,异步导出)
要在ASP.NET MVC站点上做excel导出功能,但是要导出的excel文件比较大,有几十M,所以导出比较费时,为了不影响对界面的其它操作,我就采用异步的方式,后台开辟一个线程将excel导出到指 ...
- jquery学习笔记---jquery插件开发
http://www.cnblogs.com/Wayou/p/jquery_plugin_tutorial.html jquery插件开发:http://www.cnblogs.com/damonla ...
- JUC回顾之-可重入的互斥锁ReentrantLock
1.什么是可重锁ReentrantLock? 就是支持重新进入的锁,表示该锁能够支持一个线程对资源的重复加锁. 2.ReentrantLock分为公平锁和非公平锁:区别是在于获取锁的机制上是否公平. ...
- 在MVC3或asp.net中修改KindEditor实现上传图片时添加水印
主要修改两个文件:image.js和upload_json.ashx文件. 一.修改image.js文件 打开kindeditor/plugins/image目录下的image.js文件,找到 '&l ...
- linux下php增加curl扩展,生成curl.so文件
进入php源代码目录 cd /php5.6.9/ext/curl 执行生成so文件编译模式 /usr/local/php/bin/phpize 编译curl扩展 ./configure --with- ...
- 最新版Duilib在VS2012下编译错误的解决方法
svn了好几次最新版本的项目源代码, 在VS2012下编译老是出错, 改了后没记录, 结果又忘记, 所以在此记录下. 这个问题很普遍, 非常多的人遇到. 至于 ...
- PHP实用的功能函数
/** * 获取类/对象的方法列表 *@param unknown $argument 类/对象 *@param array|string $filter 过滤 *@return array 类似:[ ...
- TeeChart注册方法
- awk命令
awk 手册 原文 Table of Contents 1. awk简介 2. awk命令格式和选项 2.1. awk的语法有两种形式 2.2. 命令选项 3. 模式和操作 3.1. 模式 3.2 ...
- new一个二维数组
.定义一个二维数组 char **array1 array1 = new char *[x]; for(i=0;i<x;++i) array1[i] = new char[y]; ...用的时候 ...