应缩小 synchronized 锁范围,仅保护真正修改共享变量的临界区;优先使用代码块级锁而非方法级锁;为不同资源分配独立锁对象以提升并发性;避免高频小锁,必要时合并为粗粒度锁。

避免 synchronized 锁范围过大,核心是“只锁真正需要保护的临界区”,而不是整个方法或一大段逻辑。锁得越宽,线程阻塞越多、上下文切换越频繁、CPU缓存失效越严重,性能瓶颈就越明显。
缩小同步块范围
把 synchronized 从方法级下放到代码块级,只包裹读写共享变量的最小片段。
- ❌ 避免:整个方法加锁(尤其含 I/O、网络调用、复杂计算)
- ✅ 推荐:仅对 count++、map.put() 等实际修改共享状态的操作加锁
- 示例:将
public synchronized void process() { load(); calc(); save(); }拆为load(); calc(); synchronized(this) { save(); }(前提是 save 才操作共享数据)
选用更细粒度的锁对象
不要默认用 this 或类对象锁,而是为不同资源分配独立锁对象,实现并发隔离。
- 比如有 userCache 和 orderCache 两个 Map,分别用
private final Object userLock = new Object();和private final Object orderLock = new Object(); - 这样更新用户缓存和订单缓存可并行,互不阻塞
- 避免所有操作都竞争同一个锁,变成“串行化执行”
用锁粗化替代高频小锁
如果同一段代码中反复对同一对象加锁/解锁(如循环内多次 synchronized),JVM 可能自动锁粗化;但更稳妥的是手动合并。
立即学习“Java免费学习笔记(深入)”;
- ❌ 不推荐:
for (int i = 0; i - ✅ 改为:
synchronized(lock) { for (int i = 0; i - 既减少锁操作次数,又避免在循环中反复进入/退出 monitor
考虑无锁或乐观策略替代
对读多写少、冲突概率低的场景,优先用原子类或 CAS,而非 synchronized。
- 计数器用
AtomicInteger替代synchronized increment() - 简单状态标志用
volatile(配合合理设计) - 集合操作优先选
ConcurrentHashMap、CopyOnWriteArrayList等线程安全容器


















