synchronized 是 JVM 内置锁,基于 monitorenter/monitorexit 指令实现,可重入、自动释放,支持实例方法、静态方法和同步代码块三种用法;Lock 是 API 显式锁,需手动加解锁,功能更丰富,支持公平性、超时、中断和 Condition。
synchronized 是 JVM 级别的内置锁
synchronized 是 Java 语言的关键字,由 JVM 直接支持,在
字节
码层面通过
monitorenter
和
monitorexit
指令实现加锁与释放。它天然支持可重入,自动管理生命周期:只要线程执行完同步块或发生异常,锁就会被释放,无需手动干预。
它可以作用于三种场景:
实例方法 → 锁对象是
this
(当前实例)
静态方法 → 锁对象是
类的 Class 对象
同步代码块 → 锁对象是括号中指定的任意对象,推荐用私有 final 对象,避免外部干扰
它的锁默认是非公平的,不支持中断等待、超时获取、条件变量等高级控制,但写法简洁、不易出错,适合逻辑简单、竞争不激烈的场景。
Lock 是 API 层面的显式锁接口
Lock 是
java.util.concurrent.locks
包中的接口,典型实现是
ReentrantLock
。它不是语法糖,而是需要程序员显式调用
lock()
加锁、
unlock()
释放锁——必须放在
finally
块中,否则可能造成死锁。
立即学习
“
Java免费学习笔记(深入)
”;
它提供的能力远超 synchronized:
Eclipse导入Android或其他的JAVA项目的正确方法 WORD版
本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
下载
可选择公平锁(构造时传
)或非公平锁(默认)
实现非阻塞尝试获取锁,返回 boolean 判断是否成功
支持超时获取,避免无限等待
让等待线程能响应 interrupt 信号
配合
实现精准唤醒(比如只唤醒“生产者”或“消费者”),比
更灵活
底层机制和性能表现不同
synchronized 在 JDK 1.6+ 后引入了锁升级机制:偏向锁 → 轻量级锁 → 重量级锁,低竞争时开销极小;高竞争下会膨胀为
操作系统
互斥量,涉及用户态/内核态切换,代价升高。
Lock(如 ReentrantLock)基于 AQS(AbstractQueuedSynchronizer)实现,使用 CAS + 自旋 + 队列等待,全程在用户态完成,高并发下更可控、更稳定。虽然现代 JVM 优化后两者性能差距已不大,但在需精细调控的场景,Lock 仍具优势。
怎么选?看实际需求
优先用 synchronized 的情况:
同步逻辑短、简单,比如计数器增减、状态标记更新
不需要超时、中断、分组唤醒等扩展功能
团队
编码
规范强调简洁性和安全性,避免手动 unlock 遗漏
考虑用 Lock 的情况:
要实现可中断的等待(如任务取消时及时释放资源)
临界区执行时间不确定,需防止单一线程长期霸占锁
需要多个 Condition 配合(如读写锁分离、生产消费解耦)
压测发现 synchronized 在高争用下成为瓶颈,且确认 Lock 可改善
基本上就这些。不复杂但容易忽略——关键是别为了“高级”而用 Lock,也别因“简单”而硬扛 synchronized 的功能短板。
truetryLock()tryLock(long, TimeUnit)lockInterruptibly()Conditionwait/notify