news 2026/4/2 9:09:13

第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/3/31 15:14:48

财务报表外币折算的技术突破与实践

在企业全球化布局中&#xff0c;财务报表外币折算始终是绕不开的难题。手工折算不仅占据报表编制时间的30% 以上&#xff0c;还频繁出现汇率类型混淆、公式编写失误等问题&#xff0c;导致最终折算数据存在异常。 多币种报表状态不同步也会导致合并时效低下&#xff0c;传统ER…

作者头像 李华
网站建设 2026/3/26 10:25:06

Linux权限配置错误导致Qwen3-VL-30B无法读取模型文件

Linux权限配置错误导致Qwen3-VL-30B无法读取模型文件 在部署阿里云旗舰级视觉语言模型 Qwen3-VL-30B 的过程中&#xff0c;团队突然发现服务启动失败。日志里反复出现 FileNotFoundError&#xff0c;提示找不到 /models/pytorch_model.bin——可明明这个文件就在那里。经过层层…

作者头像 李华
网站建设 2026/4/1 20:04:51

Conda环境导出与共享:确保PyTorch项目可复现

Conda环境导出与共享&#xff1a;确保PyTorch项目可复现 在深度学习项目的日常开发中&#xff0c;你是否曾遇到这样的场景&#xff1f;同事发来一段训练代码&#xff0c;信心满满地说“在我机器上跑得好好的”&#xff0c;结果你刚一运行就报错&#xff1a;torch.cuda.is_avai…

作者头像 李华
网站建设 2026/4/2 14:39:43

AutoGPT如何处理模糊目标?语义解析能力测试

AutoGPT如何处理模糊目标&#xff1f;语义解析能力测试 在信息爆炸的时代&#xff0c;我们每天都在面对一个共同的困境&#xff1a;想法很多&#xff0c;行动很少。你可能心里想着“我要开始健身”“想学人工智能”“准备创业做点什么”&#xff0c;但真正迈出第一步时&#xf…

作者头像 李华