什么是可重入,什么是可重入锁? 它用来解决什么问题?
                           
天天向上
发布: 2025-07-20 10:37:37

原创
878 人浏览过

在 Java 并发编程中,“可重入” 是一个非常重要的概念。它关系到线程如何获取锁,是否允许一个线程多次进入同一个锁保护的代码块


一、什么是可重入(Reentrancy)?

可重入(Reentrancy),又称“递归锁”,是指:

同一个线程在外层方法获得锁之后,在进入内层方法时如果尝试获取同一个锁,仍然能够获取成功

简单理解:

  • 自己可以再次进入自己已经拥有的锁,而不会造成死锁。

二、什么是可重入锁(Reentrant Lock)?

可重入锁是一种允许同一个线程多次获得同一把锁而不会被阻塞的锁。Java 中最常见的可重入锁有两个:

可重入锁所在包特点
synchronizedJava 语言内置关键字可重入,自动管理重入计数
ReentrantLockjava.util.concurrent.locks可重入,支持可中断、公平锁、尝试锁等特性

三、举个例子:可重入锁的代码演示

示例:synchronized 的可重入性

public class ReentrantExample {
    public synchronized void outer() {
        System.out.println("外层方法");
        inner();  // 当前线程再次进入 synchronized 方法
    }

    public synchronized void inner() {
        System.out.println("内层方法");
    }

    public static void main(String[] args) {
        new ReentrantExample().outer();
    }
}

输出:

外层方法
内层方法

即:一个线程已经持有了某对象的锁,还可以再次进入该对象的 synchronized 方法


四、ReentrantLock 的重入特性

ReentrantLock lock = new ReentrantLock();

public void outer() {
    lock.lock();
    try {
        System.out.println("outer");
        inner();
    } finally {
        lock.unlock();
    }
}

public void inner() {
    lock.lock();
    try {
        System.out.println("inner");
    } finally {
        lock.unlock();
    }
}

输出:

outer
inner

同一个线程多次调用 lock(),不会死锁,但需要手动调用多次 unlock()


五、可重入锁解决了什么问题?

如果没有可重入特性,代码中会容易出现死锁问题

// 假设锁不可重入,以下代码将死锁
synchronized(obj) {
    // 已经获得 obj 的锁
    synchronized(obj) {
        // 再次请求 obj 的锁,但锁不可重入 → 死锁!
    }
}

可重入锁解决的问题:

问题类型说明
避免死锁同一个线程可以重复进入临界区
实现递归调用同步方法 A 中调用方法 B,二者都加锁同一个对象
简化程序设计无需人为跟踪是否已持有锁

六、可重入锁底层实现机制

synchronized

  • JVM 维护一个锁计数器(reentrant count)
  • 第一次进入:计数器为 1
  • 再次进入同一锁:计数器 +1
  • 每次 exit monitor:计数器 -1,直到为 0 才真正释放锁

ReentrantLock

  • 使用一个 state 变量记录加锁次数
  • 同一个线程重复调用 lock(),state 累加
  • 每次 unlock(),state 减一,直到为 0 才释放锁

七、相关资料推荐


总结口诀

一锁在手,再进无忧;多次加锁,不死不休。
可重入锁解递归之困,防死锁于未然。


更多详细内容请关注其他相关文章!

发表回复 0

Your email address will not be published. Required fields are marked *