news 2026/7/27 6:06:45

第5章:并发与竞态条件-15:Atomic Variables

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
第5章:并发与竞态条件-15:Atomic Variables

In continuation of the previous text第5章:并发与竞态条件-14:Alternatives to Locking, let's GO ahead.

Atomic Variables

Sometimes, a shared resource is a simple integer value. Suppose your driver main-
tains a shared variable n_op that tells how many device operations are currently out-
standing. Normally, even a simple operation such as:

n_op++;

would require locking. Some processors might perform that sort of increment in an
atomic manner, but you can’t count on it. But a full locking regime seems like over-
head for a simple integer value. For cases like this, the kernel provides an atomic
integer type called atomic_t, defined in <asm/atomic.h>.

有时,共享资源只是一个简单的整数值。假设你的驱动维护着一个共享变量n_op,用于记录当前未完成的设备操作数量。正常情况下,即便是n_op++这样简单的操作,也需要加锁保护 —— 有些处理器可能会以原子方式执行这类自增操作,但你不能对此抱有依赖。不过,为一个简单整数值引入完整的锁机制显得开销过大。针对这类场景,内核提供了一种名为atomic_t的原子整数类型,定义在<asm/atomic.h>头文件中。

An atomic_t holds an int value on all supported architectures. Because of the way
this type works on some processors, however, the full integer range may not be avail-
able; thus, you should not count on an atomic_t holding more than 24 bits. The fol-
lowing operations are defined for the type and are guaranteed to be atomic with
respect to all processors of an SMP computer. The operations are very fast, because
they compile to a single machine instruction whenever possible.

atomic_t在所有受支持的架构上均存储一个整型值,但由于部分处理器的实现机制限制,其无法使用整数的完整取值范围;因此,你不应依赖atomic_t存储超过 24 位的数值。内核为该类型定义了一系列操作,这些操作能保证在 SMP(对称多处理)系统的所有处理器上都是原子执行的。这些操作执行速度极快 —— 只要有可能,它们都会被编译为单条机器指令。

/* * Set the atomic variable v to the integer value i. * You can also initialize atomic values * at compile time with the ATOMIC_INIT macro. */ void atomic_set(atomic_t *v, int i); atomic_t v = ATOMIC_INIT(0); // Return the current value of v. int atomic_read(atomic_t *v); /* * Add i to the atomic variable pointed to by v. * The return value is void, because there is an * extra cost to returning the new value, *and most of the time there’s no need to know it. */ void atomic_add(int i, atomic_t *v); // Subtract i from *v. void atomic_sub(int i, atomic_t *v); // Increment or decrement an atomic variable. void atomic_inc(atomic_t *v); void atomic_dec(atomic_t *v); /* * Perform the specified operation and test the result; * if, after the operation, the atomic value is 0, * then the return value is true; otherwise, it is false. Note that * there is no atomic_add_and_test. */ int atomic_inc_and_test(atomic_t *v); int atomic_dec_and_test(atomic_t *v); int atomic_sub_and_test(int i, atomic_t *v); /* * Add the integer variable i to v. * The return value is true * if the result is negative, false otherwise. */ int atomic_add_negative(int i, atomic_t *v); /*Behave just like atomic_add and friends, * with the exception that they return the * new value of the atomic variable to the caller. */ int atomic_add_return(int i, atomic_t *v); int atomic_sub_return(int i, atomic_t *v); int atomic_inc_return(atomic_t *v); int atomic_dec_return(atomic_t *v);

As stated earlier, atomic_t data items must be accessed only through these functions.
If you pass an atomic item to a function that expects an integer argument, you’ll get
a compiler error.

You should also bear in mind that atomic_t values work only when the quantity in
question is truly atomic. Operations requiring multiple atomic_t variables still
require some other sort of locking. Consider the following code:

如前所述,atomic_t类型的数据必须仅通过上述函数访问。若你将原子变量传递给期望接收整型参数的函数,编译器会直接报错。

你还需注意:atomic_t仅适用于 “操作本身可完全原子化” 的场景。涉及多个atomic_t变量的操作,仍需借助其他锁机制。例如以下代码:

atomic_sub(amount, &first_atomic); atomic_add(amount, &second_atomic);

There is a period of time where the amount has been subtracted from the first atomic
value but not yet added to the second. If that state of affairs could create trouble for
code that might run between the two operations, some form of locking must be
employed.

这段代码执行过程中,会存在一个时间窗口:amount已从第一个原子变量中减去,但尚未加到第二个原子变量中。如果这段时间内并发执行的代码可能因这种状态出现异常,就必须引入某种锁机制来保护。

补充说明:

  1. atomic_t 的核心特性

    • 原子性:所有操作均通过单条原子指令实现(如 x86 的lock前缀指令),避免多 CPU 并发修改导致的竞争;

    • 架构兼容性:<asm/atomic.h>会根据不同 CPU 架构(x86/ARM/RISC-V)提供适配实现,上层代码无需关注硬件差异;

    • 24 位限制:早期内核为适配部分嵌入式架构(如 ARMv5),将 atomic_t 的有效位限制为 24 位,现代内核虽放宽限制,但仍建议避免存储超过 24 位的数值(保证跨架构兼容性)。

  2. 常见错误规避

    • 禁止直接操作:不能通过v->counter(内部成员)直接修改 atomic_t,必须使用内核提供的接口,否则会破坏原子性;

    • 多变量原子操作:多个 atomic_t 的组合操作(如转账场景:A 减金额、B 加金额)不具备原子性,需额外加锁(自旋锁 / 信号量);

    • 返回值场景:若需获取操作后的新值,使用atomic_add_return等带 return 的接口,避免 “先 read 再操作” 的非原子逻辑。

  3. 适用场景

    • 计数器:如设备操作计数、中断次数统计、引用计数(替代 refcount_t,后者更安全);

    • 状态标记:如用 0/1 表示 “忙 / 闲” 状态,通过atomic_inc_and_test判断是否变为 0;

    • 轻量级同步:单变量的原子操作,替代锁以降低开销(如简单的标志位修改)。

  4. 现代内核扩展

    • 64 位原子变量:内核提供atomic64_t(定义在<linux/types.h>),支持 64 位整数的原子操作,接口与 atomic_t 一致(如atomic64_inc);

    • refcount_t:专门用于引用计数的原子类型,提供更安全的检查(如防止减到负数),替代 atomic_t 做引用计数管理。

  5. 性能对比

    • atomic_t 操作:纳秒级开销,接近普通整型运算;

    • 自旋锁:需禁用抢占 / 中断,开销约为 atomic_t 的 10~20 倍;

    • 信号量:涉及睡眠 / 唤醒,开销为 atomic_t 的百倍以上。因此,单变量的并发修改优先使用 atomic_t,而非锁机制。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/25 0:32:55

Python 1级编程考试模拟题库(5套精选)

目录Python 1级编程考试模拟题库&#xff08;5套精选&#xff09;卷1&#xff1a;基础语法与运算一、单选题 (每题2分&#xff0c;共50分)二、判断题 (每题2分&#xff0c;共20分)三、编程题 (每题15分&#xff0c;共30分)卷2&#xff1a;控制流程 (If/Else)一、单选题 (每题2分…

作者头像 李华
网站建设 2026/7/26 15:38:48

从零开始部署LobeChat:打造个人专属的大模型对话门户

从零开始部署LobeChat&#xff1a;打造个人专属的大模型对话门户 在大语言模型席卷全球的今天&#xff0c;我们早已不再满足于被动地使用AI——人们想要的是一个真正属于自己的智能助手。它不该被锁定在某个商业平台里&#xff0c;数据不透明、功能受限制&#xff1b;而应是可…

作者头像 李华
网站建设 2026/7/24 12:40:28

Jenkins环境配置篇-更换插件源

作为持续集成的利器 Jenkins 已经得到了广泛地应用&#xff0c;仅仅作为一个工具&#xff0c;Jenkins 已然有了 自己的生态圈&#xff0c;支持其的 plugin 更是超过 1300。在实际中如何使用以及如何更好地使用 jenkins&#xff0c;一直是大家在实践并讨论的。本系列文章将会从如…

作者头像 李华
网站建设 2026/7/25 16:40:44

行为驱动开发(BDD)在软件测试中的实践流程

行为驱动开发&#xff08;Behavior-Driven Development, BDD&#xff09;是一种基于敏捷方法的软件工程实践&#xff0c;它通过自然语言描述系统行为&#xff0c;弥合了业务需求与技术实现之间的鸿沟。对于软件测试从业者而言&#xff0c;BDD不仅提升了测试案例的可读性和协作效…

作者头像 李华
网站建设 2026/7/27 4:06:08

Trae的使用

一、背景 背景&#xff1a;用来快速上手使用Trae的使用&#xff0c;掌握工具的核心功能与协同开发流程&#xff0c;提升代码编写、部署与智能开发效率。 技术应用场景&#xff1a;快速搭建轻量级项目&#xff0c;借助 AiIDE 的智能代码提示 / 生成功能提升编码效率。 整体思路…

作者头像 李华
网站建设 2026/7/26 0:02:06

easy_nbt(Bugku杂项入门)

解压文件后获得一个文件夹。翻阅文件夹后发现并没有找到flag&#xff0c;但flag就在其中。先丢到winhex里面看看。发现存在很多压缩包文件&#xff0c;这说明文件夹里的很多文件其实都是压缩包。这里可以看出&#xff0c;在newword文件夹下的data文件下有压缩包&#xff0c;但我…

作者头像 李华