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

C++ 多线程与并发系统取向(五)—— std::atomic:原子操作与状态一致性(类比 Java Atomic)

一、先问一个核心问题

前面我们已经学了:

  • mutex —— 保护共享资源
  • condition_variable —— 线程协作

那为什么还需要:

std::atomic

因为有一种场景:

你不是在保护“复杂资源”
你只是想保证“某个状态是安全的”

二、atomic 解决什么问题?

atomic 解决两件事:

1️⃣ 避免数据竞争
2️⃣ 保证可见性

它适合:

  • 计数器
  • 状态标志
  • 停止信号
  • 简单数值更新

三、先看一个错误示例

bool stop = false; void worker() { while (!stop) { // do work } }

主线程:

stop = true;

你以为 worker 会停?

⚠ 可能不会。

原因:

  • 编译器可能优化
  • CPU 缓存可能导致不可见
  • 多核缓存不同步

这叫:

内存可见性问题

四、正确写法:std::atomic

#include <atomic> std::atomic<bool> stop(false); void worker() { while (!stop.load()) { // do work } }

主线程:

stop.store(true);

现在一定安全。

五、Java 类比

Java 写法:

volatile boolean stop = false;

或者:

AtomicBoolean stop = new AtomicBoolean(false);

对比:

JavaC++
volatilestd::atomic
AtomicIntegerstd::atomic<int>

区别:

C++ 的 atomic 更底层。

六、atomic 的核心特性

1️⃣ 原子性(Atomicity)

操作不会被中断。

例如:

std::atomic<int> counter(0); counter++;

不会出现:

被其他线程打断。

2️⃣ 可见性(Visibility)

一个线程写入后:

其他线程一定能看到。

3️⃣ 顺序一致性(默认)

默认使用:

memory_order_seq_cst

保证全局一致顺序。

(我们暂时不深挖内存序,只讲工程层)

七、atomic vs mutex 本质区别

对比atomicmutex
适合简单变量复杂资源
是否阻塞不阻塞可能阻塞
是否保护容器
是否能替代锁

一句话:

atomic 管“状态”
mutex 管“资源”

八、示例:多线程计数对比

错误版本

int counter = 0; void task() { for (int i = 0; i < 100000; ++i) { counter++; } }

结果不稳定。

mutex 版本

std::mutex mtx; int counter = 0; void task() { for (int i = 0; i < 100000; ++i) { std::lock_guard<std::mutex> lock(mtx); counter++; } }

正确,但性能差。

atomic 版本

std::atomic<int> counter(0); void task() { for (int i = 0; i < 100000; ++i) { counter++; } }

正确,且更高效。

九、重要误区:atomic ≠ 无锁系统

很多人会说:

那我全用 atomic 不就行了?

错误。

atomic 不能保护:

  • vector
  • map
  • queue
  • 多个变量组合状态

例如:

if (x > 0) { x--; }

即使 x 是 atomic,也可能出错。

因为:

判断 + 修改 不是一个原子事务。

十、工程级示例:停止线程

这是最常见使用场景。

#include <thread> #include <atomic> #include <iostream> #include <chrono> std::atomic<bool> running(true); void worker() { while (running.load()) { std::cout << "Working..." << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(500)); } std::cout << "Stopped." << std::endl; } int main() { std::thread t(worker); std::this_thread::sleep_for(std::chrono::seconds(3)); running.store(false); t.join(); }

这就是:

atomic 做状态控制
join 做生命周期管理

十一、atomic 的高级形态(点到为止)

atomic 还支持:

compare_exchange_strong compare_exchange_weak

用于:

  • 无锁算法
  • CAS 自旋

但:

90% 工程开发用不到。

不要一上来就写 lock-free 队列。

十二、系统取向思维升级

现在你有四层结构:

1️⃣ 线程模型 —— 谁共享
2️⃣ mutex —— 保护资源
3️⃣ condition_variable —— 线程协作
4️⃣ atomic —— 状态一致性

十三、工程口诀

状态用 atomic
容器用 mutex
等待用 condition_variable
生命周期用 join

十四、和 Java 再对比

Java:

  • synchronized = mutex
  • wait/notify = condition_variable
  • AtomicXXX / volatile = atomic

C++:

  • 更底层
  • 更危险
  • 更灵活

十五、本篇总结一句话

atomic 不是锁的替代品
它是“轻量级状态同步工具”

下一篇(真正组合拳)

第六篇我们做:

工程实战 —— 用 mutex + cv + atomic 搭一个任务系统骨架

  • 可提交任务
  • 可阻塞等待
  • 可安全关闭
  • 正确释放线程

这是你并发系统能力的第一块工程里程碑。

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

相关文章:

  • 2026.2.22
  • Python threading.Thread(target=lambda:[])
  • AI在法律尽职调查中的应用与架构实现
  • 实测50款东南亚语言配音工具,重点推荐以下性价比高的7款
  • 医疗器械手机APP开发工程师职位深度解析与面试指南
  • 深度解析:消费电子领域安卓开发工程师的核心能力与实践路径
  • 深度解析:苏州虹保世纪科技 Android 开发工程师职位要求与面试准备
  • 提示工程架构师必知:安全标准的评估方法
  • 芒格的“极端后果“思维在气候适应性技术投资中的应用
  • Python implement repeatable functions via while True loop and time.sleep
  • Python repeatable timer to implement recycled printing via schedule
  • 使用embedding进行分词 - f
  • 【开题答辩全过程】以 哈尔滨市小酒窝APP为例,包含答辩的问题和答案
  • 基于小信号建模的下垂控制稳定分析,文章完全浮现。 关键词:微电网,下垂控制,小信号模型,根轨迹...
  • flex与bison学习之字符统计程序
  • 含共享储能的园区多类型负荷需求响应经济运行研究附Matlab代码
  • 含中间直流的三相电力电子变压器PET仿真模型附Simulink仿真
  • D证科目一罚款专题
  • Java 运行时异常和编译时异常之间的区别是什么?
  • 光伏阵列常见故障仿真模型附Simulink仿真
  • 根脉与花开:AI元人文——***文化思想在智能时代的原创性理论发展
  • 什么是 Java 中的自动装箱和拆箱?
  • 光伏储能直流系统MATLAB仿真(PV光伏阵列+Boost DCDC变换器+负载+双向DCDC变换器+锂离子电池系统)附Matlab代码
  • 基于1D-GAN生成对抗网络的数据生成方法研究附Matlab代码
  • 什么是 Java 中的迭代器(Iterator)?
  • 光储直流微电网附Simulink仿真
  • 什么是 Java 的网络编程?
  • 【开题答辩全过程】以 高校学生档案管理系统为例,包含答辩的问题和答案
  • 大模型搜索引爆营销新赛道,智跑AI以GEO系统引领智能获客潮流
  • Java 中的基本数据类型有哪些?