synchronized是jvm内置隐式锁,自动加解锁;lock是jdk显式接口,需手动lock/unlock且必须配合finally,支持公平性、超时、中断、多condition等高级功能,但更易出错;简单场景优先用synchronized,复杂并发才选lock。

synchronized 和 Lock 都能实现线程同步,但设计定位、使用方式和能力边界差别明显。synchronized 是 JVM 层的内置锁机制,而 Lock 是 JDK 提供的接口,需要显式获取与释放,更灵活但也更易出错。
加锁与解锁方式不同
synchronized 是隐式锁:进入同步块或方法时自动加锁,退出时(无论正常结束还是异常)自动释放锁,无需手动干预。Lock 是显式锁:必须调用 lock() 获取,且必须在 finally 块中调用 unlock(),否则极易发生死锁。
- synchronized 可用于修饰实例方法、静态方法、代码块
- Lock 实例(如 ReentrantLock)需声明为成员变量或局部变量,通过编程控制生命周期
- 没有 try-finally 包裹 unlock(),是 Lock 使用中最常见的 bug 来源
功能扩展性差异大
synchronized 功能固定,仅支持可重入、非公平(JDK 6+ 默认偏向锁优化后行为更复杂,但语义仍受限)。Lock 接口及其实现类(如 ReentrantLock)提供丰富能力:
- 可选择公平锁或非公平锁(构造时指定)
- 支持尝试获取锁(tryLock()),避免无限等待
- 支持带超时的锁获取(tryLock(long, TimeUnit))
- 可中断地获取锁(lockInterruptibly())
- 可绑定多个 Condition 对象,实现精确唤醒(synchronized 只能用 wait/notify,且只能有一个隐式条件队列)
性能与底层机制不同
早期 synchronized 性能较差,但自 JDK 6 起经过大量优化(偏向锁、轻量级锁、自旋锁、锁消除、锁粗化),在多数简单同步场景下性能已不输甚至优于 ReentrantLock。Lock 的优势不在“一定更快”,而在于可控性和适应复杂并发逻辑的能力。
- synchronized 锁信息保存在对象头(Mark Word)中,由 JVM 直接管理
- ReentrantLock 底层基于 AQS(AbstractQueuedSynchronizer)实现,依赖 CAS + volatile + 队列
- 高竞争、需精细控制的场景(如自定义同步策略、分段唤醒),Lock 更合适
语法与可读性对比
synchronized 写法简洁,天然与作用域绑定,阅读成本低;Lock 需要多行代码,容易因疏忽导致资源泄漏,但配合 try-with-resources(需自行包装成 AutoCloseable)可提升安全性。
- 推荐优先用 synchronized:逻辑简单、作用域明确、无需特殊功能时
- 只有明确需要 tryLock、可中断、多 Condition 或公平性控制时,才选用 Lock
- 不要为了“看起来更高级”而滥用 Lock
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











