核心区别在于锁的范围、锁对象可控性及并发性能影响:同步方法锁定整个方法体且锁对象隐式(this或class),易导致假竞争;同步块仅锁定关键代码并支持显式指定锁对象,粒度更细、性能更优、更易规避死锁。

核心区别在于锁的范围、锁对象的可控性,以及对并发性能的影响。
锁的作用范围不同
普通方法加 synchronized 会锁定整个方法体,从进入方法开始到方法结束,锁一直持有。哪怕方法里只有几行代码真正访问共享资源,其余逻辑(比如日志、计算、IO)也会被阻塞。
- 同步方法:所有调用该方法的线程,必须排队等待前一个线程执行完整个方法
- 同步块:只包裹真正需要互斥的代码,比如对集合的 add/remove 操作,前后无关逻辑可并发执行
锁对象的选择自由度不同
修饰普通方法时,锁对象是隐式的:
- 实例方法 → 锁的是 this(当前对象)
- 静态方法 → 锁的是 类的 Class 对象(如 MyClass.class)
同步块则允许你显式指定任意非空对象作为锁:
- 可以用私有 final 对象(推荐:
private final Object lock = new Object();),避免被外部干扰 - 也可用特定资源对象(如
synchronized(map)),实现更精准的资源级控制 - 不建议用
this或getClass()做同步块锁,容易引发子类或外部代码意外竞争
性能与实际适用场景差异明显
方法级同步粒度粗,容易造成“假竞争”——多个线程本可并行执行,却因锁住整方法而被迫串行。
- 适合逻辑简单、全部操作都依赖同一状态的场景(如 getter/setter 封装简单字段)
- 同步块更适合真实业务:比如一个方法中只有 2 行修改 HashMap 的代码需要同步,其余都是耗时 IO 或本地计算,这时只锁那 2 行,能显著提升吞吐量
- 同步块还更容易规避死锁:你可以按固定顺序获取多个锁,或使用 tryLock 等更细粒度控制
本质都是同一套锁机制,关键在怎么用
synchronized 方法和同步块底层都基于 JVM 的 monitor 机制,不是两种不同的锁。区别全在于开发者如何划定临界区、选择锁目标、控制持有时间。
- 不要为了“看起来简洁”而滥用同步方法,尤其当方法变长或职责变多时
- 同步块不是更复杂,而是更务实——它迫使你思考:到底哪段代码真需要互斥?谁该持有这把锁?
- 多数现代 Java 项目中,同步块配合私有锁对象,已成为保护共享状态的主流写法
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











