清远市网站建设_网站建设公司_产品经理_seo优化
2025/12/17 20:59:59 网站建设 项目流程

原子操作是指不可被中断的单个或一组操作
在多线程环境下,原子操作的执行过程中不会被其他线程打断,要么完全执行完毕,要么完全不执行,不存在 “执行一半” 的中间状态。
它的核心价值是解决多线程对共享数据的竞态条件(Race Condition) 问题(比如两个线程同时读写同一个变量,导致数据错乱),是实现线程安全的基础,无需依赖互斥锁(如std::mutex)即可保证简单数据操作的安全性。
非原子操作的反例(多线程修改同一个变量):

#include <iostream>
#include <thread>
using namespace std;int Counter = 0;void Increment() {for (int i = 0; i < 100000; ++i) {Counter++; // 非原子操作!}
}int main() {thread t1(Increment);thread t2(Increment);t1.join();t2.join();cout << "Counter = " << Counter << endl; // 结果大概率≠200000return 0;
}

输出结果:Counter = 105516 每次不一样
原因分析:
Counter++ 看似是 “一步操作”,实际拆解为 3 个步骤:
1.读取Counter的当前值到寄存器;
2.寄存器值 + 1;
3.把新值写回Counter。
多线程执行时,可能出现 “线程 A 读值后,线程 B 抢先修改并写回,线程 A 再写回旧值 + 1” 的情况,导致计数丢失。

C++11 引入头文件,提供std::atomic模板类,封装原子操作,支持常见数据类型(int/bool/指针等)。
而原子操作能让Counter++变成 “不可拆分” 的一步,避免上述问题。
加入原子操作后:

#include <iostream>
#include <thread>
#include <atomic> // 原子操作头文件
using namespace std;atomic<int> Counter = 0; // 原子整型void Increment() {for (int i = 0; i < 100000; ++i) {Counter++; // 原子自增,等价于 Counter.fetch_add(1)}
}int main() {thread t1(Increment);thread t2(Increment);t1.join();t2.join();cout << "Counter = " << Counter << endl; // 结果必然=200000return 0;
}

输也结果:Counter = 200000

核心操作(以std::atomic为例)
a.load() 原子读取值(默认内存序memory_order_seq_cst) 等价原生指令(x86): mov
a.store(val) 原子写入值 等价原生指令(x86): mov
a++/a-- 原子自增 / 自减(语法糖) 等价原生指令(x86): lock xadd
a.fetch_add(n) 原子加 n,返回旧值 等价原生指令(x86): lock xadd
a.fetch_sub(n) 原子减 n,返回旧值 等价原生指令(x86): lock xadd
a.exchange(val) 原子替换值,返回旧值 等价原生指令(x86): xchg
a.compare_exchange_weak(expected, desired) 比较并交换(CAS):若a==expected,则设为desired,返回 true;否则更新expected为a的当前值,返回 false 等价原生指令(x86): lock cmpxchg

原子操作的底层机制分析上面的代码:
无原子操作时:
Counter++会拆分为 3 步:
mov eax, [Counter](读值到寄存器);
add eax, 1(寄存器 + 1);
mov [Counter], eax(写回内存)。
此时线程协调会出问题,比如:

时间片 Core0(t1) Core1(t2) Counter 值 问题
1 读 Counter=0 到 eax - 0 -
2 - 读 Counter=0 到 eax 0 两个线程都读到旧值 0
3 eax+1=1 eax+1=1 0 都计算出 1
4 写回 Counter=1 - 1 t1 先写回
5 - 写回 Counter=1 1 t2 覆盖 t1 的结果,丢失一次自增

上面 两次读写同样的数,覆盖了,造成数据缺失

而原子操作通过lock xadd把 “读 - 改 - 写” 打包成不可拆分的指令,从硬件层面杜绝了 “线程 A 读值后,线程 B 抢先修改” 的情况
代码中Counter是std::atomic类型,Counter++是原子自增操作—— 它不是普通的 “读 - 改 - 写” 三步,而是被 CPU 封装成「不可中断的单一指令」,这是线程协调的核心。
原子操作的底层实现(x86 平台为例)
Counter++(原子自增)对应的 CPU 指令是:lock xadd dword ptr [Counter], 1
xadd:是 “交换并相加” 指令,完成「读取值→加 1→写回值→返回旧值」的完整逻辑;
lock前缀:是 CPU 的 “总线锁定 / 缓存锁定” 机制 ——在执行xadd期间,锁定 Counter 对应的内存地址,禁止其他 CPU 核心(线程)访问该地址,直到指令执行完毕。
这是原子操作能 “协调” 多线程的硬件基础:任何时刻,只有一个线程能执行对 Counter 的原子操作,其他线程必须等待。

时间片 Core0(t1) Core1(t2) Counter 值 关键说明
1 执行Counter++(lock xadd) 等待(总线被 Core0 锁定) 0→1 t1 的原子操作独占内存,t2 无法打断
2 释放总线锁定 执行Counter++(lock xadd) 1→2 t2 抢占到总线,执行原子操作
3 执行Counter++(lock xadd) 等待(总线被 Core0 锁定) 2→3 交替执行,无冲突
... 循环执行剩余 99997 次自增 循环执行剩余 99998 次自增 ... 每次自增都是原子的,无中间状态
最终 执行完 10 万次 执行完 10 万次 200000 所有操作无丢失,结果准确

关键:内存序(Memory Order)
原子操作的 “内存可见性” 可通过内存序优化(默认是最严格的memory_order_seq_cst,性能稍低),常见内存序:
memory_order_relaxed:仅保证操作本身原子性,不保证内存可见性(最快,适用于无依赖的计数);
memory_order_acquire:读操作,保证后续操作能看到当前操作的结果;
memory_order_release:写操作,保证当前操作的结果对后续读操作可见;
memory_order_seq_cst:顺序一致性(默认),所有线程看到的操作顺序一致(最安全,性能稍差)。
示例( Relaxed 内存序优化计数):

atomic<int> Counter = 0;
void Increment() {for (int i = 0; i < 100000; ++i) {Counter.fetch_add(1, memory_order_relaxed); // 仅需原子性,无需严格内存序}
}

UE5 中的原子操作(与标准 C++ 的关联)
FPlatformAtomics::InterlockedOr/InterlockedAnd等函数,本质是 UE 对平台相关原子操作的封装(兼容 Windows/Linux/PS5 等平台),对应标准 C++ 的原子操作:
FPlatformAtomics::InterlockedOr → 原子按位或(等价于atomic::fetch_or);
FPlatformAtomics::InterlockedAnd → 原子按位与(等价于atomic::fetch_and);
FPlatformAtomics::AtomicRead_Relaxed → 放松内存序的原子读(等价于atomic::load(memory_order_relaxed))。
比如 UE5 中UObjectBase的原子标志位操作:

// UE5原子设置标志位(核心逻辑)
FPlatformAtomics::InterlockedOr((int32*)&ObjectFlags, FlagsToAdd);
// 等价于标准C++
atomic<int32> objFlags;
objFlags.fetch_or(FlagsToAdd);

原子操作 vs 互斥锁

特性 原子操作 互斥锁(std::mutex)
适用场景 简单数据操作(计数、标志位、CAS) 复杂操作(多步逻辑、跨资源访问)
性能 极快(无内核态切换) 较慢(可能触发内核态切换)
功能 仅支持基础数据操作 支持任意临界区保护
死锁风险 有(如锁顺序错误)

核心总结
原子操作是 “不可中断” 的操作,解决多线程共享数据的竞态条件;
C++ 通过的std::atomic实现,UE5 通过FPlatformAtomics封装平台相关原子操作;
优先用原子操作处理简单数据(计数、标志位),复杂逻辑用互斥锁;
内存序可优化性能,按需选择(非特殊场景用默认seq_cst即可)。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询