← 每日面试题 学习看板

并发编程中的原子性和数据库ACID的原子性一样吗?

面试题/00java/02Java 并发编程/09编程实践与应用场景/并发编程中的原子性和数据库ACID的原子性一样吗?.md

面试记录 2026-10-20

题目:并发编程中的原子性和数据库ACID的原子性一样吗?

难度:medium

标签:java/concurrency-practice, java/concurrency

评分:⭐⭐⭐☆☆(3/5)

我的回答

并发编程的原子性和数据库中的原子性不是一个概念;

并发编程的原子性是一个操作在是不可再分的,一个指令就完成,不会有多个指令,一次就完成,比如赋值操作,或者通过锁使得一组操作只有一个线程完成,其他线程阻塞不能进入执行临界区;

数据库ACID中的原子性是事务下,一组操作执行要么都成功,要么都失败是事务下整个事务操作的原子性

点评

优点:核心区别一次说中——并发原子性是"不可分割的单个操作",ACID 原子性是"事务内多个操作的全或无";知道用锁把一组操作变原子

不足:① 未提原子性的实现手段(CAS/AtomicInteger、synchronized 的内存屏障)与破坏原子性的经典例子(i++ 三条指令);② 未提 ACID 原子性靠 undo log 回滚实现;③ 未点出两者真正的联系——单机原子性无法跨进程,所以才有分布式事务(2PC/TCC 本质是"把原子性从单库扩展到多库");④ 缺"可见性/有序性不因原子性而保证"

补充:并发原子性 = 单条指令或临界区不可分割;ACID 原子性 = 事务要么全提交要么全回滚,靠 undo log;两者在"全或无"语义上同构,但作用域与实现完全不同

完整讲解

第一部分:知识重点剖析

核心考点定位:能否把"单机指令级原子"与"事务级全或无"分开,并说清各自的实现机制与作用域。

知识点拆解:

  1. 并发原子性:一个或多个操作在执行过程中不被其他线程打断;最小粒度是 CPU 指令(如 MOV、CAS),i++ 是"读-改-写"三条指令,天然不原子
  2. 并发原子性的实现:AtomicInteger 用 CAS 自旋(Unsafe.compareAndSwapInt);synchronized/Lock 用互斥把复合操作包成临界区;LongAdder 用分段累加降低争用
  3. ACID 原子性:事务内所有 DML 要么全部生效、要么全部回滚;实现依赖 undo log 反向补偿 + redo log 保证崩溃恢复
  4. 两者的联系:语义上都是"全或无",但作用域不同——并发原子性作用于单进程内存,事务原子性作用于单个存储引擎;跨库就失效,于是需要 2PC/TCC/Saga
  5. 常见混淆点:原子性 ≠ 可见性 ≠ 有序性;volatile 保证可见性与有序性但不保证原子性;AtomicInteger 保证单个变量原子但不保证复合逻辑原子(先查再改仍需锁)
按「底层原理 → 设计权衡 → 工程实践」递进排列。

第二部分:考察方向与延伸递进

考察方向:

延伸递进面试题:

  1. AtomicInteger 能保证 if (count < 10) count++ 的原子性吗?
  1. synchronized 和 CAS 各自适合什么场景?
  1. 数据库事务原子性和分布式事务原子性的差别?

第三部分:面试者参考回答(三步法)

【一句话结论】

面试官您好,两者都讲"全或无",但一个是单条指令不可分割,一个是整个事务可回滚,作用域和实现完全不同。

【三点展开】

第一,并发原子性控制在指令和临界区级别。i++ 编译出来是读、加、写三条指令,两个线程交错就会丢更新;解决要么用 CAS 自旋,要么用锁把这三条包成临界区。

第二,ACID 的原子性是事务级别的全或无,靠 undo log 反向补偿实现——中途失败就拿 undo 把已执行的语句逐条撤销,再配合 redo log 保证崩溃后能恢复到一致状态。

第三,两者的联系在于"作用域"。单机原子性出了进程就失效,所以跨库转账才需要 2PC 或 TCC;而 TCC 的 Cancel 本质是"用业务补偿模拟回滚",拿不到数据库那种真正的原子回滚。

【一句边界】

当然,原子性不等于线程安全——volatile 有可见性、有序性但不保证原子性;AtomicInteger 保证单变量原子,但"先判断再修改"这种复合逻辑还是得靠锁或 CAS 循环。