当前位置:网站首页>嵌入式环境下并发控制与线程安全
嵌入式环境下并发控制与线程安全
2022-07-30 11:27:00 【李肖遥】
关注、星标公众号,直达精彩内容
来源:网络素材
代码规模日益增大和基于RTOS的多线程技术使嵌入式软件开发越来越关注“并发控制和线程安全”,当多个执行线程(指正在运行代码的任意上下文,包括线程和中断服务程序)需要访问相同的共享资源时(包括软件数据和硬件资源),就可能因为竞态而导致错误。
这种错误容易制造,但很难找到,从设计上保证正确性收益更大。
竞态的产生
当一个共享资源被多个执行线程“非原子性”访问时,一个执行线程的操作被另一个执行线程打断而带来错误就叫“竞态”,共享资源包括硬件设备和软件实体。
最明显的共享是全局变量,如果定义如下数组,它被多个线程读和写,这将成为最易理解的竞态。
int g_aiGlobalBuf[100];另一种不太明显的共享是由不可重入函数造成的,如果多个线程调用了下面的函数,那么同样产生竞态。
void ProcGlobalBuf(int iPos, int iVal)
{
g_aiGlobalBuf[iPos] = iVal;
}硬件资源被多个线程使用也会引入竞态,如下面的函数(使用伪代码)被2个线程同时调用,那么第一个线程的数据可能还没有发送完毕就被第二个线程的数据“覆盖”。
void SendByDMA(const void *p_vBuf, int iSize)
{
DMA.StartAddr = p_vBuf;
DMA.Count = iSize;
EnableDMA();
}一句话:任何被多个执行线程使用的资源都可能产生“竞态”。
并发控制规则
规则一:只要可能,就应该避免资源的共享。
如果没有并发访问,就不会有竞态的产生。因此,设计代码应该具有最少的共享。这种思想的最明显应用是避免使用全局变量。如果我们将资源放在多个执行线程都会找到的地方,则必须有足够的理由。
例如硬件资源的分配中,串口只能由线程1调用,网口只能由线程2调用,LCD只能由线程3调用,那么这3种硬件资源的竞态一开始就杜绝了,同理可以应用到软件资源上。
规则二:引发竞态的共享资源必须加锁
然而,在计算机的世界里共享就是现实的生活,在单个执行线程之外共享硬件或软件资源的任何时候,因为另外一个线程可能产生对该资源的不一致观察,就必须显示地管理对该资源的访问。
像只读数据(如芯片的序列号)对于任何访问它的执行线程看来都是一致的,那么竞态是不可能发生的。
基于RTOS的嵌入式环境下对共享资源的加锁一般有3种途径:关中断、使用信号量、禁止任务切换。
关中断应用于2种情况:如果任务代码和中断程序共享资源,或者共享资源访问时间很短(如操作一个变量);如果仅线程之间访问一些共享资源且操作时间不太长,禁止任务切换可以胜任;其他情况下都将使用信号量。
规则三:被多线程调用的函数必须是可重入
一个函数是否是可重入的判断规则:
一个可重入函数一般用原子的方法使用变量,除非这些变量存储在调用这个函数的堆栈中或这些变量是任务的私有变量。
一个可重入函数一般不调用其他的不可重入的函数。
一个可重入函数一般不用非原子的方法使用硬件。
锁的使用规则
当我们创建一个可被并行访问的对象时,应该同时定义用来控制访问的锁。锁定模式必须在一开始就安排好,否则其后的改进将会非常困难。
如果某个获得锁的函数要调用其他同样试图获取这个锁的函数,我们的代码就会死锁,即不允许锁拥有者第二次获得这个锁;如果试图这么做,系统将持起。
提供给外部调用的函数必须显示地处理锁定,在编写那些假定调用者已处理了锁定的内部函数时,我们自己应该显示地说明这种假定,否则几个月后再回头来看这些代码时,很难记清在调用某个特定函数时是否需要拥有锁。
尽可能避免出现需要多个锁的情况,实在需要多个锁就要防止死锁的发生:始终以相同的顺序获得锁,并且了解其他代码操作锁的做法;先获取自己局部锁,再获取其他锁;在拥有锁时尽量避免线程被挂起,那样会导致实时性下降,甚至永久性挂起系统。
原文链接:https://blog.csdn.net/jiangjunjie_2005/article/details/30713585
版权声明:本文来源网络,免费传达知识,版权归原作者所有。如涉及作品版权问题,请联系我进行删除。
‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧ END ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧
关注我的微信公众号,回复“加群”按规则加入技术交流群。点击“阅读原文”查看更多分享,欢迎点分享、收藏、点赞、在看。边栏推荐
- 单片机开发之LCD1602显示实验
- TensorFlow custom training function
- LeetCode_236_Last Common Ancestor of a Binary Tree
- ORA-00600 [13013], [5001], [268] 问题分析及恢复
- 听到'演员工作比工人辛苦,吃得也不如工人好?'我笑了
- salesforce使用方法(salesforce authenticator下载)
- 基于.NetCore开发博客项目 StarBlog - (16) 一些新功能 (监控/统计/配置/初始化)
- [ASP.NET Core] Dependency Injection for Option Classes
- "Learning Cloud Networking with Teacher Tang" - Problem Location - The host is working but the container is not working
- 自定义查询--关于倒排索引的研究
猜你喜欢

周鸿祎:微软抄袭了360安全模式 所以成为美国最大的安全公司

Typroa 替代工具marktext

Horizontal comparison of 5 commonly used registration centers, whether it is used for interviews or technical selection, is very helpful

Leetcode 125. 验证回文串

SCM engineers written questions induction summary

Still using Swagger?I recommend this interface management artifact with zero code intrusion

反转链表-递归反转法

NLP领域的最新研究进展

面试官:Redis中的布隆过滤器与布谷鸟过滤器,你了解多少?

win下怎么搭建php环境的方法教程
随机推荐
Detailed explanation of @RequestBody and @ResponseBody
域名怎么注册备案解析?
Redis 主从复制
The battle-hardened programmer was also deceived by a fake programmer from a certain fish. The trust between programmers should be the highest, and he alone destroyed this sense of trust
听到'演员工作比工人辛苦,吃得也不如工人好?'我笑了
Microsoft SQL server hacked, bandwidth stolen
数字量输入输出模块DAM-5088
decodeURIComponent(), eval(), encodeURIComponent()
decodeURIComponent()、eval()、encodeURIComponent()
TensorFlow自定义训练函数
[Cloud-Building Co-creation] Huawei Cloud and Hongmeng collaborate to cultivate innovative developers
美团内推+校招笔试题+知识点总结
单片机开发之LCD1602显示实验
English line break
Program environment and preprocessing (detailed)
Static LED display developed by single chip microcomputer
Native js create table
ADC0808/9 signal acquisition developed by single chip microcomputer
久经沙场的程序员居然也被某鱼的假程序员骗了,程序员之间的信任应该是最高的,他一个人毁了这种信任感
物联网技术概论:第6章