1. 为什么我们需要超越 synchronized?
在 Java 并发编程领域,synchronized 关键字就像是一把瑞士军刀 - 简单易用但功能有限。我见过太多开发者把 synchronized 当作解决所有并发问题的银弹,直到他们在高并发场景下遇到性能瓶颈或是复杂的同步需求时才意识到问题的严重性。
synchronized 的局限性主要体现在三个方面:首先,它是非公平锁,无法保证等待时间最长的线程最先获取锁;其次,它不支持中断,一旦线程开始等待锁就无法被中断;最重要的是,它缺乏灵活的锁获取机制,比如尝试获取锁、定时等待等功能。这些限制在构建复杂的并发系统时会成为明显的障碍。
实际案例:在一个电商平台的秒杀系统中,使用 synchronized 导致大量线程阻塞,最终系统吞吐量下降到无法接受的水平。改用 ReentrantLock 后,通过公平锁策略和尝试获取锁机制,系统性能提升了3倍。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. ReentrantLock 的核心优势解析
2.1 可重入性设计原理
ReentrantLock 的可重入特性是其最基础也是最重要的特性。所谓可重入,指的是同一个线程可以多次获取同一把锁而不会导致死锁。这个特性通过一个计数器实现 - 每次获取锁计数器加1,释放锁时计数器减1,只有当计数器归零时锁才真正释放。
java复制public void methodA() {
lock.lock();
try {
methodB(); // 可重入调用
} finally {
lock.unlock();
}
}
public void methodB() {
lock.lock(); // 同一线程可再次获取锁
try {
// 业务逻辑
} finally {
lock.unlock();
}
}
2.2 公平锁与非公平锁的抉择
ReentrantLock 提供了公平锁和非公平锁两种模式。公平锁按照线程请求的顺序分配锁,而非公平锁则允许插队。虽然公平锁听起来更合理,但在实际应用中非公平锁的性能通常更好,因为减少了线程切换的开销。
java复制// 创建公平锁
ReentrantLock fairLock = new ReentrantLock(true);
// 创建非公平锁(默认)
ReentrantLock unfairLock = new ReentrantLock();
性能测试数据:在100个线程竞争的场景下,非公平锁的吞吐量比公平锁高出约40%。但在线程等待时间差异较大的场景中,公平锁能提供更可预测的性能。
2.3 灵活的锁获取机制
ReentrantLock 提供了多种锁获取方式,这是它相比 synchronized 的最大优势:
- tryLock():尝试获取锁,立即返回成功或失败
- tryLock(lo
