synchronized 合理使用需缩小同步范围、明确锁对象、避免耗时操作和死锁。优先用 synchronized(锁对象) 代替同步方法,用 private final object 或 class.class 作锁,按固定顺序获取多把锁,利用其可重入性但注意不可中断。

synchronized 是 Java 最基础的线程同步工具,用得好能保障线程安全,用得随意则容易拖慢性能、引发死锁。关键不在“用不用”,而在“怎么用更合理”。
缩小同步范围,只锁真正共享的部分
锁整个方法(尤其是 public 方法)往往过度保护。比如一个方法里只有 2 行代码操作共享变量,其余都是本地计算或 I/O,那就该只同步那 2 行。
- 优先用 synchronized(锁对象) { ... } 替代 synchronized 方法
- 把临界区控制在最小粒度,例如只包裹
counter++,而不是整个日志打印 + 计数 + 返回值逻辑 - 避免在同步块内做耗时操作(如网络请求、文件读写、sleep),否则其他线程会长时间阻塞
明确锁对象,避免用 this 或 public 对象
用 this 作锁,等于把对象的内部同步机制暴露给外部;如果别人也能拿到这个实例并调用 synchronized(this),就可能意外干扰你的同步逻辑。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 声明一个 private final Object lock = new Object(); 作为专用锁
- 静态资源统一用 ClassName.class,不要用
new Object()或任意实例 - 不同业务逻辑尽量用不同锁对象,避免“一把锁管所有”,降低争抢概率
注意锁的获取顺序,预防死锁
当一段逻辑需要多个锁时(比如先更新账户 A,再更新账户 B),如果线程 1 按 A→B 顺序加锁,线程 2 按 B→A 顺序加锁,就极易形成循环等待。
- 约定全局一致的锁顺序:例如按 ID 升序、按类名字母序、或固定字段名排序后依次获取
- 必要时使用 tryLock() + 超时(需切换到 ReentrantLock),但 synchronized 本身不支持尝试获取
- 避免在持有锁时调用外部不可控方法(如回调、接口实现),防止对方反向加锁
理解可重入性,别误判嵌套问题
synchronized 是可重入锁,同一线程再次进入同一把锁的同步块不会被阻塞——这是设计使然,不是 bug。
- 常见场景:同步方法内部调用另一个本类的同步方法,无需额外处理
- 不必为“防止自己锁自己”而绕弯设计,JVM 已通过计数器自动管理
- 但要注意:可重入 ≠ 可中断,synchronized 等待锁的过程无法响应 interrupt
不复杂但容易忽略——真正影响并发表现的,往往不是锁有没有,而是锁在哪、锁多久、锁谁。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










