当前位置: 首页 > 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.rkmt.cn/news/14079.html

相关文章:

  • 复刻江协旋钮控制模块
  • c语言switch和if语句
  • Qt(制作一个方便的文本编辑器)
  • tldr的安装与利用
  • 题解:P7126 [Ynoi2008] rdCcot
  • 实用指南:汽车地带AutoZone EDI需求分析及对接指南
  • 航司网站url后缀参数FECU分析
  • 优化 if/else 的四种设计模式
  • 多corner综合
  • Day11-C:\Users\Lenovo\Desktop\note\code\JavaSE\Basic\src\com\oop\demo06
  • OpenLayers地图交互 -- 章节十一:拖拽材料交互详解
  • 通过IDOR实现权限提升导致未授权用户注入
  • kuboard使用的etcd空间满了如何处理
  • 从拆盒到共创:手办盲盒抽赏小程序的多元体验与文化联结 - 实践
  • xinference推理embedding等小模型
  • day15-项目上线
  • Docker入门 - 实践
  • react useCallback Hook详解
  • 实用指南:小米17手机的上市公司供应商
  • cloudfared 内网穿透经过docker方式遇到的问题
  • CDN + WAF + CLB + Higress 架构下的 TLS 加解密详细解析(适用阿里云)
  • CF407E k-d-sequence 题目分析(0929模拟赛最后一题)
  • vue3踩坑:静态dom无法初始化渲染 - 父组件props与侦听器的交互
  • Mysql DBA学习笔记(客户端常用工具) - 教程
  • MATLAB 中 dsp.FFT 系统对象:从原理到实践的完整指南
  • C# Devexpress GridControl实现全选功能(转载,记录)
  • Nordic发布用于nRF54L系列的nRF Connect SDK裸机选项
  • 微软SSO集成中的顺序用户ID身份验证绕过漏洞剖析
  • shell脚本动态域名解析阿里云
  • 对称加密和非对称加密原理对比