找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1169|回复: 9
打印 上一主题 下一主题
收起左侧

两个线程读写1个变量需要保护吗?一个是中断任务,一个是普通任务

[复制链接]
跳转到指定楼层
楼主
ID:885416 发表于 2022-3-30 21:43 来自手机 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
比如一个变量,有两个线程读写,比如说一个是中断任务,一个是普通任务,直接用volatile行吗?
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:883242 发表于 2022-3-30 23:13 | 只看该作者
这就是原子操作的概念。
以八位机为例,主循环:
int i;
i++;
对于8位机i是16位的,这个i++会分解成两个操作:
i.low++;
i.high+=CY;
设i=255,那么实际操作就是:
i.low++; //i.low=0
i.high+=CY;  //i.high=1
这个代码正常工作的话,i++的结果将是i=0x100也就是i=256,这个结果是正确的。

但是如果某个中断程序也要读取i的值,在i.low++之后发生了中断,那么中断读到的i的值将是一个极其不合理的0!这会导致中断处理程序发生异常操作!

所以,只要不是原子操作,主循环和中断共享变量的话,一定要关闭中断防止非原子操作被中断打断!上面代码正确的写法是:

IE=0; //关中断
i++;
IE=1; //开中断
回复

使用道具 举报

板凳
ID:885416 发表于 2022-3-30 23:33 来自手机 | 只看该作者
Hephaestus 发表于 2022-3-30 23:13
这就是原子操作的概念。
以八位机为例,主循环:
int i;

大佬,如果是32位,不存在这个高低位情况下,单片机把一个变量加1,是先把变量从内存取出到寄存器,让后把寄存器这个数加1,类似ADD R1 1这样的指令,让后放回内存里,是这个流程吗?

如果先从内存取变量值为3到寄存器这个过程后,就发生了中断,中断里改变了内存里这个变量的值为5,然后中断结束,任务恢复,让后任务把寄存器里的3加1变成4,再放回内存,那么是不是这个变量的值就会发生错误?
回复

使用道具 举报

地板
ID:883242 发表于 2022-3-31 00:37 | 只看该作者
azjdly 发表于 2022-3-30 23:33
大佬,如果是32位,不存在这个高低位情况下,单片机把一个变量加1,是先把变量从内存取出到寄存器,让后 ...

单一的机器指令不会被打断,所以不需要考虑原子操作问题。

主贴我忘了回答volatile问题,加不加volatile关键字跟原子操作没任何关系。
回复

使用道具 举报

5#
ID:123289 发表于 2022-3-31 08:50 | 只看该作者
只能依据你的需要判定。
回复

使用道具 举报

6#
ID:415064 发表于 2022-3-31 09:05 | 只看该作者
读的话不需要保护,写是要保护的,volatile也没用
回复

使用道具 举报

7#
ID:401564 发表于 2022-3-31 15:55 | 只看该作者
赞同5楼的说法
要看你自己的需要去操作
一个普通任务,一个中断,操作同一个变量,有可能出现的情况就是:你要普通任务中操作到一半的时候,中断又去对这个变量进行操作,这就容易出现混乱
不管是8位机还是32位,都是一样的,你都不知道你的代码最后会被编译成什么,就算是32位,你也不能保证你的代码是一个时钟就能完成的
所以,只能根据你自己的需要来操作
回复

使用道具 举报

8#
ID:1012747 发表于 2022-3-31 16:04 | 只看该作者
中断会导致挂起当前操作,从正常设计上来说你这个一般是需要去读当前这个变量的,写的话一般设计阶段就得避免了,至于你描述的情况,除非你设计的时候就要做这样的操作,否则就是设计上的bug。
这个应该按照楼上几位大佬说的,根据你自己的需求从设计上进行操作。
然后是volatile的限定符的目的是警告编译器不要进行假定的优化。主要是为了避免编译器优化导致莫名其妙的问题的。
所以,最后就又回到你的需求上了。
回复

使用道具 举报

9#
ID:883242 发表于 2022-4-1 17:26 | 只看该作者
Y_G_G 发表于 2022-3-31 15:55
赞同5楼的说法
要看你自己的需要去操作
一个普通任务,一个中断,操作同一个变量,有可能出现的情况就是:你 ...

以我在沙发位的8位机例子为例,如果i是char型的,那么i++就是原子操作,无需保护,主循环可以随便改,中断也可以随便读。

什么是原子操作?原子操作只有2种状态,一种是没做,一种是做完了,看不到正在做的状态。你连代码会编译成什么都不知道还是不要误导他人了。
回复

使用道具 举报

10#
ID:401564 发表于 2022-4-1 17:30 | 只看该作者
Hephaestus 发表于 2022-4-1 17:26
以我在沙发位的8位机例子为例,如果i是char型的,那么i++就是原子操作,无需保护,主循环可以随便改,中 ...

对的对的,你说的是对的
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表