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

news/2025/9/29 19:54:37/文章来源:https://www.cnblogs.com/wzzkaifa/p/19119415

【多线程】什么是原子操作(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.mzph.cn/news/922201.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

详细介绍:视频融合平台EasyCVR构筑智慧交通可视化管理与智能决策中枢

详细介绍:视频融合平台EasyCVR构筑智慧交通可视化管理与智能决策中枢pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: &q…

php高性能网站建设深圳微信网站开发公司

今日分享阿里云一面,给要准备就业的宝子们一点方向 1、自我介绍与项目介绍 2、八股文 Java的特性、Java的oop? Java有哪些方法来实现线程安全? 讲讲Spring中的AOP与IOC? synchronized锁怎么用? Mysql中右模糊查询用…

docker 在x86上build arm 镜像

好——你想在 x86 主机上构建 ARM 镜像(比如为 Raspberry Pi 或者 ARM 服务器构建 linux/arm64 / linux/arm/v7)。下面给出一套实用、可直接复制执行的步骤、常用命令、以及常见问题与优化建议,覆盖从环境准备到构建…

网站开发用什么系统比较好?网站建设维护合同模板

前言 大家好,我是来自CSDN的寄术区博主PleaSure乐事。今天是开始学习vue的第一天,我使用的编译器是vscode,浏览器使用的是谷歌浏览器,后续会下载webstorm进行使用,当前学习阶段使用vscode也是可以的,不用担…

9.29软工

今天学了很多,就得靠练。

手机怎么做黑网站网络公司网络推广

AES加密是美国联邦政府采用的一种块加密标准,如今已经被全世界广为使用。嵌入式开发中我们也经常会用到加密解密算法,如果没有硬件模块来实现,就需要用到C代码软件实现。下面介绍调用mbedTLS中的AES加密解密函数实现AES算法。 mbedTLS是一个…

不一样的.NET烟火,基于Roslyn的开源代码生成器

功能介绍 Mud 代码生成器是一个基于Roslyn的源代码生成器,专为.NET开发者设计,用于根据实体类自动生成各种相关的代码,从而显著提升开发效率。它具有以下核心功能:DTO代码生成 - 根据实体类自动生成数据传输对象(…

详细介绍:深入浅出 XSS — 从原理到实战与防护

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

房屋在线设计网站个人网站怎么做打赏

我叫白天涯,来自计科13-1班。 首次使用这个博客园发表随笔,请大家多多关照。 本次软件工程课我希望能好好听讲,认真做课堂记录,不会的及时问老师,以及跟同学沟通,尽管我计算机这方面不是太精通,…

vxe-table 数据量过大时切换空白

vxe-table 数据量过大时切换空白问题 vxe-table单页数据超过100条时,切换页签会导致表格区域出现空白。此时滚动鼠标,数据会重新出现。 解决 给 vxe-table 标签上添加 :scroll-y="{ gt: -1 }"即可禁用虚拟…

复刻江协旋钮控制模块

复刻江协旋钮控制模块 1、初始化硬件 OLED初始化这里就不展开细讲了,可以看我之前的帖子复刻江协激光触发器旋钮初始化使能外部中断模式改为上拉根据旋钮接口接上线2、操作代码 (1) 初始化输出定义全局变量count,并初…

做自行车车队网站的名字展厅搭建公司

一、引入 在没有遇见mapstruct的时候,实现各个实体之间的转换,都是手动转换实现的,属性少一带你还好,当属性一多,代码就会变得很冗余,没必要的非逻辑的代码就会加多。。。。 比如: public cl…

Linux 基础IO与系统IO - 实践

Linux 基础IO与系统IO - 实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco"…

从零开始,使用Idea工具搭建一个springboot项目

一,搭建之前准备 搭建之前先确保本机已正确安装JDK,Maven,IDEA。 以下是我的配置: OpenJDK 17 Maven 3.9.11 IDEA 2025 二,开始搭建1,打开Idea工具,File->New-> Project...2,左边选择“Spring Boot"…

最优/极值问题的算法选择

如何选择滑动窗口、二分、动态规划算法 刷leetcode时对于一些最优/极值问题往往不知采用哪一种算法,故借助大模型学习一些算法要点。1. 滑动窗口(Sliding Window) 特点适用于 数组 / 字符串 的 连续子区间 问题。 目…

珠海的门户网站有哪些深圳地址大全

ScottPlot是一款简单易用、高度定制、性能卓越的.NET绘图库,支持跨平台操作。除提供标准图表类型外,还支持交互式操作,呈现生动的数据展示。在工厂数字化系统中,可用于生产数据可视化、设备监测和质量控制。无论用于科学研究、数据…

网站开发和推广方案永康市建设银行网站查询

PHP程序的调试一直是一件让人头疼的事,它既不像VB等高级语言那样有集成的编译调试环境,也不想Perl那样可以在Linux或者DOS环境下直接运行。其实,我们完全可以通过灵活地使用echo语句来完成对PHP的调试工作。下面的几个函数可以让你随时查看程…

梁山网站建设多少钱wordpress文章末尾添加内容

前言 有时遇到这样的需求,就是在表格里面嵌入一个表格,以及要求带有分页,这样在ElementPlus中很好实现。以下使用Vue2语法实现一个简单例子,毕竟Vue3兼容Vue2语法,若想要Vue3版本例子,简单改改就OK了。 一…

外贸建站wordpress昆山网站建设jofuns

以下内容整理于Linux字符设备驱动剖析,如有侵权请告知删除 。 一、应用层的程序 应用程序一般都是open打开设备文件,read、write、ioctl设备文件,最后close设备文件退出。 int main(int argc ,char *argv[]) { unsigned char val[1] 1; …

第三方控件库的添加和使用

添加把第三方控件库先复制到根目录下 ,也就是Debug 的目录下然后再拖到工具箱的空白处下就可以了使用 和之前的控件使用相同 ‍