synchronized 合理使用需精准选择锁对象、控制粒度、缩小范围:用私有final对象锁特定字段,避免字符串字面量锁;读写分离,仅锁必要状态变更;复合操作统一锁序防死锁;高并发场景结合atomicinteger、stampedlock或分片锁优化。

synchronized 在处理复杂共享资源时,关键不在“能不能用”,而在于“怎么锁才合理”——锁对象选得准、粒度控得住、范围缩得小,才能兼顾线程安全与执行效率。
明确锁对象,避免隐式共享
复杂资源常由多个子组件构成(如订单对象含用户信息、商品列表、支付状态),若直接用 this 或 getClass() 锁整个实例或类,容易造成过度串行。应为不同逻辑维度准备独立锁对象:
- 用私有 final 对象锁特定字段:例如
private final Object paymentLock = new Object();,只保护支付状态更新 - 对集合类操作,优先锁封装它的容器对象,而非集合本身(避免外部误锁)
- 避免使用字符串字面量或公共对象(如
"lock"、System.out)作锁,防止意外的锁竞争
缩小同步范围,分离读写逻辑
复杂资源往往读多写少,且读操作本身不改变状态。synchronized 不适合包裹整段业务流程,尤其不能包含 I/O、远程调用或长耗时计算:
- 把数据校验、本地计算等非共享操作移出 synchronized 块
- 读操作若无需强一致性(如统计看板),可配合
volatile字段或无锁结构(如ConcurrentHashMap)降低开销 - 写操作中,仅锁定真正需要互斥的字段赋值或状态转换部分,例如只锁
order.setStatus(ORDER_PAID)这一行,而非整个支付完成流程
应对复合操作,保证原子性不中断
复杂资源的状态变更常依赖多个变量协同(如库存扣减 + 订单创建 + 日志记录),单靠 synchronized 方法无法覆盖跨对象协作。此时需注意:
- 若涉及多个对象,统一约定锁顺序(如先锁商品再锁订单),防止死锁
- 对必须原子执行的多步操作,用同一个锁对象包裹全部步骤,不可拆成多个 synchronized 块
- 避免在 synchronized 块内调用外部可重入方法(如回调、监听器),以防锁被意外释放或递归加深
结合更高阶工具,不硬扛高并发
当复杂资源面临持续高并发(如秒杀场景下的库存),单纯靠 synchronized 容易退化为重量级锁,引发线程阻塞和上下文切换开销:
- 考虑用
java.util.concurrent中的专用工具:如AtomicInteger管理计数类字段,StampedLock支持乐观读 - 对资源做分片(如按商品 ID 取模分库/分段锁),把大锁拆成多个小锁,提升并行度
- 必要时引入分布式锁(如 Redisson),但仅限跨 JVM 场景;单 JVM 内仍优先用 synchronized 或 ReentrantLock
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











