synchronized易被误用,应缩小锁粒度、选用私有final对象作锁、注意可见性边界、避免锁升级开销。需仅保护临界区,禁用字符串或this作锁,volatile不能替代synchronized,高读低写可选StampedLock。

Java 中 synchronized 是最常用也最容易被误用的同步机制。它本身简洁可靠,但若不理解其行为边界和运行时开销,很容易在高并发场景下拖慢系统——不是它“慢”,而是用法不当放大了竞争代价。
锁粒度太大导致线程排队拥堵
把整个方法或大段逻辑包进 synchronized,等于让所有线程争抢同一把钥匙。哪怕只有一行代码真正需要保护,其余部分也被迫阻塞。
- 避免写
public synchronized void process() { ... }这类全方法同步 - 只对读写共享变量的临界区加锁,例如
count++前后几行 - 考虑拆分锁:不同业务字段用不同锁对象(如
private final Object lockA = new Object();),降低争用概率
锁对象选择错误引发意外串行
锁对象要是可变、可共享或不可控的,就可能让本不该互斥的代码块互相阻塞。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 别用字符串字面量(如
"lock")或公共静态对象作锁——它们可能被其他模块复用 - 避免用
this作为锁对象,尤其在类可能被继承或暴露给外部调用时 - 推荐声明私有 final 对象:
private final Object lock = new Object();,明确作用域且不可替换
忽视可见性与原子性边界
synchronized 确保了原子性和可见性,但只对括号内的代码生效。一旦跳出同步块,变量状态就不再受保障。
立即学习“Java免费学习笔记(深入)”;
- 不要在同步块外读取刚更新的共享变量,除非再次加锁或用
volatile修饰 -
volatile不能替代synchronized:它不保证i++这类复合操作的原子性 - 高频读+低频写的场景,可考虑
StampedLock或ReadWriteLock提升吞吐
忽略锁升级与 JVM 优化机制
JDK 1.6+ 对 synchronized 做了大量优化,但前提是竞争不激烈。一旦锁升级为重量级,线程挂起/唤醒开销会明显上升。
- 监控应用中
Monitor的等待时间(可通过 JFR 或jstack观察 BLOCKED 线程数) - 若发现大量线程在同一个锁上等待,优先检查是否能减少临界区执行时间(比如把耗时 IO 移出同步块)
- 在极轻量级竞争场景,
ReentrantLock提供更细的控制(如tryLock、公平策略),但多数情况synchronized更轻量


















