++、|=)→ 必须原子操作或临界区一句话:"volatile 保新鲜,原子保完整,临界区保不被打断。"
原子操作 = "不可分割"的操作——要么完整执行要么完全不执行,中途不可能被打断。保护共享数据三手段:volatile(每次读新值)、临界区(关中断)、硬件原子指令(单条完成读-改-写)。volatile 管"看得见新值",原子管"操作不拆开",临界区管"代码不被打断"。
count++; = LOAD→ADD→STORE 三步,中断/另一任务可插入 → 丢更新count++ → 三步非原子| volatile | 临界区 | 原子指令/原子类型 | |
|---|---|---|---|
| 管什么 | 每次读新值(可见性) | 一段代码不被中断打断 | 单次读-改-写不可分割 |
| 代价 | 无 | 关中断,影响实时性 | 几乎无 |
| 适用 | 单个读/写 | 任意代码段/复杂流程 | 简单变量操作 |
volatile uint32_t reg; 一任务写一任务读 → 不需要原子操作(对齐 32 位单读/单写天然原子,volatile 够)volatile uint32_t *p 指向不对齐地址 → 不是天然原子(可能被拆成多次总线访问,如协议帧内)count |= 0x01; 中断也操作 count → 读-改-写,需临界区或原子操作++ 用关中断是杀鸡用牛刀,简单操作优先原子指令;临界区真正怕的是"太长",会饿死中断++ 不适合临界区(它恰恰是保护对象,只是原子指令更省)| 相邻概念 | 和本主题的关系 | 孤立理解会犯的错 |
|---|---|---|
| volatile | volatile 保"每次读新值",原子保"读-改-写不拆开",独立可叠加 | 以为 volatile 就够原子 |
| 临界区 | 关中断保护任意代码,代价是实时性 | 临界区开太久饿死中断 |
| 中断优先级 | 中断里只能用 FromISR 的 API | 在中断里调用会阻塞的 API |
| SMP/多核 | 关中断只管本核,多核要真原子/锁 | 以为关中断多核也安全 |
2026-08-03
每主题一页,复习时只翻本目录。