Linux内核中并发与竞争的产生原因及原子操作的解决方案,梳理:
一、并发与竞争的核心问题
Linux作为多任务操作系统,多线程、抢占式调度、中断、SMP多核等场景会导致多个执行流同时访问共享数据,若不加控制,可能引发数据混乱(如示例中变量 a 的值被意外覆盖),甚至系统崩溃。
核心矛盾:共享数据的非原子操作被打断,导致操作结果不可控。
二、原子操作的作用
原子操作通过保证“操作不可分割”(即汇编指令级的不可中断),解决单个变量的并发访问问题。对于整型变量,Linux提供了 atomic_t (32位)和 atomic64_t (64位)两种原子类型,配套的API函数确保对其 counter 成员的读写、增减等操作是原子性的。
三、 atomic_t 操作API的关键说明
- 初始化与读写
ATOMIC_INIT(i) :定义时初始化原子变量(如 atomic_t b = ATOMIC_INIT(0) )。
atomic_read(v) :安全读取原子变量的值(避免读取过程中被其他操作修改)。
atomic_set(v, i) :原子地设置变量值,替代直接赋值(防止多步汇编被打断)。
- 增减操作
基础操作: atomic_add(i, v) 、 atomic_sub(i, v) 、 atomic_inc(v) (自增)、 atomic_dec(v) (自减),仅修改值,无返回。
带返回值的操作: atomic_inc_return(v) (自增后返回新值)、 atomic_dec_return(v) (自减后返回新值),适用于需要立即判断结果的场景。
- 条件判断操作
如 atomic_dec_and_test(v) :自减后判断是否为0,常用于“资源计数为0时触发动作”(如释放资源)。
这类函数将“修改+判断”合并为原子操作,避免“先判断后修改”的竞态(如判断时为1,修改前被其他执行流减为0,导致错误)。
四、64位原子操作
对于64位SOC, atomic64_t 结构体及配套API(如 atomic64_read 、 atomic64_add 等)与32位逻辑一致,仅针对64位数据设计,满足更大数值范围的原子操作需求。
原子操作是解决单个整型变量并发问题的轻量级方案,适用于计数器、引用计数等场景。但需注意:
仅支持整型变量,无法直接保护复杂数据结构(如结构体、链表)。
需根据CPU位数选择 atomic_t (32位)或 atomic64_t (64位),避免数据截断或性能问题。