当前位置: 首页 > news >正文

【多线程】什么是原子操作(Atomic Operation)? - 详解

【多线程】什么是原子操作(Atomic Operation)?

本文来自于我关于多线程系列文章。欢迎阅读、点评与交流
1.什么?就是【多线程】互斥锁(Mutex)
2.【多线程】临界区(Critical Section)是什么?
3.【多线程】计算机领域中的各种锁
4.【多线程】信号量(Semaphore)是什么?
5.【多线程】信号量(Semaphore)常见的应用场景
6.【多线程】条件变量(Condition Variable)是什么?
7.【多线程】监视器(Monitor)是什么?
8.原子操作(Atomic Operation)?就是【多线程】什么

原子管理(Atomic Operation)是一个非常核心的计算机概念,涉及到并发编程的底层基础。我们来详细拆解一下。

什么?就是1. 原子操作

简单来说,原子操作是一个不可分割的操作。在执行过程中,它要么完全执行成功,要么完全没执行,不会出现执行到一半被中断的情况,外界也看不到中间状态。

你可以把它想象成一个“瞬间完成”的操作。

一个经典的非原子操作例子:i++
这个看似简单的语句,在CPU层面通常需要三个步骤:

  1. 读取:从内存中读取变量 i 的值到寄存器。
  2. 修改:在寄存器中将值加一。
  3. 写入:将新值写回内存。

在单线程环境下,这没问题。但在多线程或多核环境下,障碍就来了:

  • 线程 A 读取 i 的值为 10。
  • 线程 A 将值加一,变成 11(还在寄存器中,未写回)。
  • 此时,线程 B 被调度,它读取 i 的值,仍然是 10
  • 线程 B 将值加一,变成 11(寄存器中)。
  • 线程 B 将 11 写回内存。
  • 线程 A 被重新调度,也将 11 写回内存。

最终结果 i 等于 11,但两个线程各执行了一次 i++,我们期望的结果应该是 12。这就是因为 i++ 不是原子操作,导致了数据竞争

原子操作的例子:使用原子加执行。
如果 fetch_add 是一个原子操作,那么整个“读取-修改-写入”序列会被捆绑成一个不可分割的单元。

  • 线程 A 开始执行原子加操控。它会“锁定”这个变量(注意,这里的锁定是硬件层面的机制,不是软件互斥锁)。
  • 在线程 A 达成整个操作(读取、加一、写入)之前,线程 B 无法访问或修改这个变量。
  • 线程 A 完成后,i 变为 11。
  • 11,加一后变为 12 并写回。就是线程 B 开始执行原子加操作,读取到的值

最终结果 i 等于 12,符合预期。

原子操作的核心特性:

  • 不可分割性:操作要么全做,要么不做。
  • 顺序性内存屏障的一种,能保证指令执行顺序,避免编译器或CPU的指令重排优化带来问题。就是:原子操作本身

2. 底层是如何建立的?

原子操作的实现不依赖于操作系统或编程语言提供的锁(如 mutex),因为锁本身的实现又需要原子操作。这是一个“先有鸡还是先有蛋”的问题。原子操作的基石是硬件支持,主要是CPU提供的指令。

实现方式可以分为两大类:

方式一:单核处理器

在单核CPU上,实现原子操作相对简单。因为同一时刻只有一个线程在执行(宏观并行,微观串行)。只需要保证在执行原子管理的指令序列期间不被中断即可。

  • 实现方法:在执行关键的几条指令之前关闭中断,执行完毕后再打开中断。这样,操作系统就无法通过时钟中断来剥夺当前CPU的执行权,从而不会发生线程/进程切换,保证了操作的原子性。
方式二:多核处理器

这是现代计算机的常态,也是复杂性的来源。关闭一个核心的中断无法阻止其他核心同时访问同一块内存。

核心机制:基于总线锁和缓存一致性协议(MESI)。

1. 总线锁(Bus Locking) - 古老而管用的方法

2. 缓存锁(Cache Locking) - 现代主流方法

具体的原子指令:
CPU提供了一些直接支持原子操作的机器指令,最常见的包括:

编程语言(如C++的 std::atomic,Java的 java.util.concurrent.atomic 包)和操作系统API最终都会将这些原子指令封装成易用的函数供开发者调用。

总结

特性原子操作互斥锁(Mutex)
实现层级硬件指令(CPU)操作系统内核(软件)
粒度很细,针对单个内存地址较粗,保护一个临界区代码
开销非常低,通常由缓存一致性协议保证较高,需要陷入内核态,可能引起线程挂起和调度
应用场景容易的计数器、标志位、无锁数据结构保护复杂的逻辑代码块或数据结构
关系是实现互斥锁的基础在原子运行(如CAS)之上搭建

简单来说,原子操控是CPU提供的一种硬件能力,通过总线锁或更高效的缓存锁(基于MESI协议)来保证对单一内存单元的“读-改-写”操作不可分割。它是构建一切高级并发控制工具的基石。

http://www.jsqmd.com/news/6183/

相关文章:

  • 详细介绍:视频融合平台EasyCVR构筑智慧交通可视化管理与智能决策中枢
  • docker 在x86上build arm 镜像
  • 9.29软工
  • 不一样的.NET烟火,基于Roslyn的开源代码生成器
  • 详细介绍:深入浅出 XSS — 从原理到实战与防护
  • vxe-table 数据量过大时切换空白
  • 复刻江协旋钮控制模块
  • 第三方控件库的添加和使用
  • 实用指南:基于 HTML、CSS 和 JavaScript 的智能图像灰度直方图匹配系统
  • C4NR PVP服务器1.2 天穹炮塔更新
  • 树形dp [JOI Open 2020] 发电站 / Power Plant
  • 深入解析:灵画-AI绘画小程序
  • 实用指南:CAN邮箱深度解析:从硬件架构到实战应用
  • 产品排序
  • c语言switch和if语句
  • Qt(制作一个方便的文本编辑器)
  • DeepSeek-V3.2-Exp 完整分析:2025年AI模型突破与稀疏注意力技术深度解析
  • Java EE初阶启程记05---线程安全 - 指南
  • tldr的安装与利用
  • DataGridView表格控件使用说明
  • 题解:P7126 [Ynoi2008] rdCcot
  • MyBatis技术详解:从入门到高效开发 - 详解
  • 解码数据结构队列
  • 实用指南:Linux Shell 脚本:从零到进阶的实战笔记
  • 解决升级 Windows 11 24H2 后 NAS 共享无法显示的问题
  • 实用指南:汽车地带AutoZone EDI需求分析及对接指南
  • 商城类电商购物APP网购原型——实战计划原型
  • 【还未找到原题】宝石(GEM) - Harvey
  • 第八篇
  • C# AStar 算法 - 实际应用