synchronized通过强制互斥执行保障原子性:同一时刻仅一个线程可进入临界区,确保读-改-写等复合操作不可分割;底层由monitorenter/monitorexit指令配合monitor锁实现,且支持可重入,避免嵌套中断。

synchronized 通过强制互斥执行来保证操作的原子性。它不改变单条指令本身是否原子(比如 int i = 1 是原子的,但 count++ 不是),而是让一段逻辑在运行时“不可分割”——同一时刻只允许一个线程进入,其他线程必须等待,从而避免执行中途被抢占或穿插。
原子性不是指单条语句,而是指代码块的执行整体不可中断
Java 中很多看似简单的操作实际由多步指令组成。例如 count++ 包含三步:
① 从主内存读取 count 值到线程工作内存;
② 执行加 1 运算;
③ 将结果写回主内存。
若无同步,两个线程可能同时读到旧值(如都读到 0),各自加 1 后都写回 1,导致丢失一次更新。
synchronized 不会把这三步变成一条 CPU 指令,而是确保:只要一个线程开始执行这个代码块,其他线程就无法“插队”,必须等它完整走完读→算→写全过程后才能进入。
底层靠 monitor 锁和字节码指令保障执行独占
JVM 在编译 synchronized 代码时,会插入 monitorenter 和 monitorexit 两条字节码指令:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
立即学习“Java免费学习笔记(深入)”;
-
monitorenter出现在同步块入口:线程必须先成功获取对象监视器(monitor)锁,才能继续执行后续代码; -
monitorexit出现在同步块出口:无论正常结束还是抛出异常,JVM 都会自动触发释放锁; - 锁对象可以是任意 Java 对象(包括 this、类对象、自定义锁对象),关键在于所有竞争线程使用的是同一个锁实例。
可重入性避免死锁,也维持了原子性语义
synchronized 是可重入锁。同一个线程再次进入自己已持有的锁所保护的同步块时,不会被阻塞,而是直接通行,并增加锁计数。这保证了:
- 递归调用或嵌套同步不会意外中断当前正在执行的原子逻辑;
- 即使线程在同步块中被调度器切换出去(如时间片用完),锁仍被持有,其他线程无法介入,恢复执行后能继续完成剩余步骤;
- 整个临界区始终以“全有或全无”的方式被一个线程串行执行。
与 volatile 的关键区别:volatile 不提供原子性
虽然 volatile 能保证变量修改对其他线程立即可见(可见性),也能禁止某些重排序(有序性),但它完全不阻止多个线程同时执行读-改-写操作。例如:
-
volatile int count = 0;+count++→ 仍是非原子的,结果依然可能出错; - 只有配合 synchronized(或
AtomicInteger等原子类),才能真正解决count++类操作的原子性问题。

















