C++ std::atomic在ISR与主循环共享变量场景下的使用疑问
问题解答
1. 原子类型在ISR上下文的运作逻辑
C++标准定义的原子类型核心保证是操作的不可分割性,这个特性和执行上下文无关,不需要原子机制感知当前是在ISR还是普通线程/主循环:
- 对于对齐的整型变量(你示例中的int属于这类),主流架构下原子的读、写、读改写操作都会被编译器映射为单CPU指令,而CPU响应中断的时机是指令执行间隙,所以单指令操作不管在主循环还是ISR中执行,都不可能被中断打断,天然满足原子性要求。
- 部分架构下复杂的原子操作可能会用到总线锁机制,这种机制的有效性也不依赖执行上下文,即使在ISR中执行也能保证操作不被其他总线主设备(比如DMA、其他核心)打断,不会出现操作半完成的状态。
- ISR不可被中断的特性不仅不会影响原子操作的正确性,反而会进一步降低冲突概率:主循环的原子操作只会被ISR打断,而ISR的原子操作不会被主循环打断,两者的操作始终是串行执行的,不会出现并行冲突。
2. 操作有效性保证
你要求的两个特性都可以得到保证:
- 只要ISR被正常触发,
x++作为原子操作一定会完整执行,不会出现执行到一半被切走的情况,x的值要么完全不更新,要么完全更新为自增后的值,不存在中间态。 - 主循环中
y = x的原子读操作,一定会读到x的完整有效值:要么是ISR执行x++前的旧值,要么是x++执行完成后的新值,不会读到部分位更新的脏值,完全符合你的要求。
额外优化建议
如果是嵌入式裸机场景,你可以显式指定宽松内存序进一步降低开销,对这个场景功能没有影响:
#include <atomic> std::atomic<int> x; void isr() { // 仅保证自增操作原子性,不需要额外内存同步 x.fetch_add(1, std::memory_order_relaxed); } void loop() { // 仅保证读取操作原子性,不需要额外内存同步 int y = x.load(std::memory_order_relaxed); }
只要你使用的工具链的C++标准库适配当前硬件平台,以上实现就和你之前用汇编封装的atomic_get效果完全一致,不需要额外做中断屏蔽之类的操作。
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

