synchronized的原子性是逻辑上的串行执行而非指令级原子,依赖jvm监视器机制实现互斥;其可重入、粗粒度同步,与cas等硬件级原子操作有本质区别。

Java 中 synchronized 关键字实现的“原子性”并非底层指令级的原子操作,而是通过互斥锁保障临界区代码的**串行执行**,从而在逻辑上达成原子效果。
同步块的本质是互斥,不是 CPU 原子指令
synchronized 并不依赖单条不可分割的 CPU 指令(如 lock xchg),而是基于 JVM 的监视器(Monitor)机制:每个对象关联一个 Monitor,线程进入同步块前必须获取该 Monitor 的所有权。若 Monitor 已被占用,线程阻塞等待;获取成功后才执行同步代码,退出时自动释放 Monitor。
- JVM 将
synchronized编译为monitorenter和monitorexit字节码指令 - 底层由操作系统互斥量(mutex)或 CAS + 自旋等机制实现 Monitor 的争用与调度
- 即使同步块内包含多条语句(如读-改-写),只要被同一把锁保护,就对外表现为“不可分割”的整体行为
原子性只在锁作用域内成立
所谓“原子操作”,仅针对被同一把锁保护的代码段而言。它不改变单条 Java 语句本身的非原子性(例如 i++ 仍是读、加、写三步),而是阻止其他线程在执行过程中插队。
- 错误示例:
synchronized(this) { a = 1; b = 2; }是原子的;但若a和b被不同锁保护,就无法保证二者更新的可见性与顺序一致性 - 关键点:原子性取决于锁的粒度和范围,而非语句本身是否简单
- 没有锁保护的变量读写仍可能被重排序,需配合 volatile 或锁来保证 happens-before 关系
可重入性确保同一线程多次获取同一锁安全
同一个线程可以重复进入由自己持有的 synchronized 锁(包括同步方法和同步块),JVM 会维护锁的计数器(Entry Count)。每次进入加 1,每次退出减 1,直到归零才真正释放锁。
- 避免了死锁风险:比如同步方法内部调用另一个同步方法(相同锁对象)不会阻塞
- 可重入性是实现封装和组合的关键,否则递归调用或委托调用极易出错
- 注意:不可重入锁(如某些自定义锁)需额外设计,而
synchronized天然支持
与真正的原子类(如 AtomicInteger)区别明显
synchronized 提供的是**粗粒度的代码块级同步**,而 java.util.concurrent.atomic 包中的类利用 CPU 的 CAS 指令实现无锁的、细粒度的变量级原子更新。
- CAS 是硬件级原子操作(如 x86 的
cmpxchg),适用于简单状态变更(如计数器增减) -
synchronized更适合保护复杂业务逻辑(含多个变量、IO、条件判断等) - 性能上:高竞争下 CAS 可能因自旋耗 CPU,而 synchronized 在 JDK 6+ 后已优化(偏向锁→轻量锁→重量锁),实际差距缩小
不复杂但容易忽略:synchronized 的原子性是协作式保障,依赖开发者正确选择锁对象、控制同步范围,并理解其与内存可见性、重排序的关系。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











