synchronized通过monitor机制保障原子性、可见性和有序性:加锁确保同一时刻仅一个线程执行临界区,释放锁前刷新变量至主内存以保证可见性,加解锁处插入内存屏障防止指令重排。

synchronized 通过强制串行化访问共享资源,从原子性、可见性、有序性三个层面保障多线程数据安全。它不是靠“魔法”,而是基于 JVM 的监视器(monitor)机制和内存模型约束来实现的。
锁住临界区,保证操作原子性
多个线程对同一共享变量做“读—改—写”(如 count++)时,若不加控制,可能丢失更新。synchronized 把这类非原子操作包裹进一个不可分割的执行单元:
- 进入 synchronized 方法或代码块前,线程必须先获取对应对象的 monitor 锁;
- 未释放锁前,其他线程无法进入同一把锁保护的任何同步区域;
- 即使方法内部有多条语句(比如先判断再修改),整个块被视为一个整体执行,不会被中途打断。
刷新缓存,确保修改对其他线程可见
每个线程有自己的工作内存,可能缓存旧值。synchronized 在释放锁时会强制将本地修改刷回主内存;在获取锁时会清空本地缓存,重新从主内存加载最新值:
- 线程 A 修改 count 并退出 synchronized 块 → count 新值写入主内存;
- 线程 B 随后进入同一把锁的 synchronized 块 → 强制读取主内存中的 count,看到 A 的修改;
- 这解决了 volatile 无法覆盖的“复合操作+可见性”双重问题。
插入内存屏障,防止指令重排破坏逻辑顺序
编译器和 CPU 可能优化指令顺序,导致看似合理的代码在并发下行为异常。synchronized 在加锁与解锁处插入内存屏障(Memory Barrier):
立即学习“Java免费学习笔记(深入)”;
- 加锁前:禁止把临界区内的读写指令重排到锁外;
- 解锁后:禁止把锁外的读写指令重排到临界区内;
- 从而保证“先写后读”的执行时序,满足并发准确性核心原则。
注意锁对象的选择与粒度
锁的安全效果完全取决于是否用对了锁对象:
- 实例方法上的 synchronized 锁的是 this,适用于单个对象状态;
- 静态方法上的 synchronized 锁的是 当前类的 Class 对象,用于保护类级别共享变量;
- 同步代码块可指定任意对象作为锁,但多个线程必须竞争同一把锁才有效——用 new Object() 每次新建就等于没锁;
- 锁粒度越粗(如整个方法),并发性越低;锁粒度越细(如只锁关键几行),性能越好,但需确保逻辑完整性。


















