Java中ReentrantLock的「可重入」特性到底是什么含义?
可重入锁常见疑问解答
针对你提出的几个疑问逐一解答如下:
疑问1解答:你的理解完全正确,可重入的核心定义就是已经持有某把锁的线程,可以无需再次竞争直接进入该锁保护的其他代码段。
你看到的嵌套synchronized方法就是最典型的场景,以下是极简示例:public class ReentrantDemo { public synchronized void methodA() { System.out.println("进入methodA,锁计数+1"); methodB(); // 这里就是重入调用,不需要再次争抢当前对象的监视器锁 } public synchronized void methodB() { System.out.println("进入methodB,锁计数再+1"); } }如果锁不支持可重入,这种嵌套调用场景会直接触发死锁:线程已经持有锁,又要等待自己释放锁,永远无法继续执行。
疑问2解答:答案是肯定的,不管是JVM实现的
synchronized还是JDK实现的ReentrantLock,可重入特性的核心实现逻辑就是维护持有计数。同一线程每成功重入一次,计数就会+1。疑问3解答:必须调用和重入次数相等的
unlock()(对应synchronized就是退出对应数量的同步块/方法)才能完全释放锁。
以ReentrantLock的使用为例:ReentrantLock lock = new ReentrantLock(); try { lock.lock(); // 首次加锁,计数变为1 try { lock.lock(); // 重入加锁,计数变为2 // 执行业务逻辑 } finally { lock.unlock(); // 计数减1,当前为1,锁仍然被当前线程持有 } } finally { lock.unlock(); // 计数减1,当前为0,锁完全释放,其他线程可以争抢 }如果重入3次只调用1次
unlock(),锁会一直被当前线程持有,其他线程永远无法获取,因此使用显式锁时一定要保证加锁次数和unlock()调用次数完全匹配,建议把unlock()放在finally块中,避免异常导致漏调用。
补充你可能没注意到的可重入特性其他要点:
- 可重入是线程维度的规则,只要是同一个持有锁的线程,不管是同一方法递归调用,还是同一锁保护的不同方法互相调用,都属于合法重入,可以直接进入。
- 你提到的「
tryLock()是ReentrantLock和synchronized的核心区别」这个说法不准确:二者都属于可重入锁,核心差异是锁的实现层面和灵活性:synchronized是隐式锁,加锁解锁由JVM自动处理,不需要手动操作;ReentrantLock是显式锁,需要手动调用lock()/unlock(),支持超时获取、可中断获取、公平锁配置等synchronized不具备的特性,tryLock()只是灵活性特性中的一个,不是核心区别。 - 公平模式下的
ReentrantLock重入不会破坏公平规则:当前线程已经是锁的持有者,重入时不需要参与等待队列排队,不会插队到其他等待线程前面。 - 可重入锁最核心的设计价值就是避免同一线程嵌套调用同步代码时的死锁风险,目前工业界常用的锁实现默认都是可重入的,不可重入锁仅在极少特定场景下使用。
内容的提问来源于stack exchange,提问作者user1354825
相关产品推荐
相关产品推荐

