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 ...
随机推荐
- 《Java并发编程实战》学习笔记 线程安全、共享对象和组合对象
Java Concurrency in Practice,一本完美的Java并发参考手册. 查看豆瓣读书 推荐:InfoQ迷你书<Java并发编程的艺术> 第一章 介绍 线程的优势:充分利 ...
- async/await 异步编程
前言 最近在学习Web Api框架的时候接触到了async/await,这个特性是.NET 4.5引入的,由于之前对于异步编程不是很了解,所以花费了一些时间学习一下相关的知识,并整理成这篇博客,如果在 ...
- Android VLC播放器二次开发1——程序结构分析
最近因为一个新项目需要一个多媒体播放器,所以需要做个视频.音频.图片方面的播放器.也查阅了不少这方面的资料,如果要从头做一个播放器工作量太大了,而且难度也很大.所以最后选择了VLC作为基础,进行二次开 ...
- hdu 5312 数学
- spring classpath & classpath*
classpath-找到系统类路径下的第一个匹配的配置文件 classpath*-找到系统类路径下的所有符合要求的配置文件 参考资料:http://www.micmiu.com/j2ee/spring ...
- String 和 document 的相互转换总结
转自:http://blog.sina.com.cn/s/blog_7f865faf01014qrs.html 一.使用最原始的javax.xml.parsers,标准的jdk api // 字符串转 ...
- 【spring bean】bean的配置和创建方式
---恢复内容开始--- 项目结构如下: lib如下: 1.首先建立SayHell.java接口 package com.it.sxd; public interface SayHell { publ ...
- CDH中,如果管理CM中没有的属性
在CM配置管理中的"hive-site.xml 的 Hive 客户端高级配置代码段(安全阀)""仅适用于高级使用,逐个将字符串插入 hive-site.xml 的客户端配 ...
- unity 播放过场动画
public var url="file:///c:/sample.ogg"; //文件路径 function Start () { //拼凑一个url url="fil ...
- CC150 - 11.2
Question: Write a method to sort an array of strings so that all the anagrams are next to each other ...