什么是可重入,什么是可重入锁? 它用来解决什么问题?

可重入(Reentrant)与可重入锁(Reentrant Lock)详解


1. 可重入(Reentrant)

定义
可重入指的是一段代码(如函数、方法或同步块)可以被同一线程多次安全地进入,而不会引发死锁或数据不一致问题。这里的“安全”体现在:

  • 不依赖全局变量或静态数据。

  • 对共享资源的操作是原子的或通过同步机制保护的。

解决的问题
在多线程或递归调用场景中,如果一个线程在持有锁的情况下再次尝试获取同一锁,若锁不可重入,会导致线程自己阻塞自己(死锁)。可重入机制通过允许同一线程重复获取锁,避免了这一问题。

示例

public synchronized void methodA() { methodB(); // 调用另一个同步方法 } public synchronized void methodB() { // 若锁不可重入,methodA调用methodB时会死锁 }

在可重入机制下,线程进入methodA获取锁后,调用methodB时能再次获取同一锁,继续执行。


2. 可重入锁(Reentrant Lock)

定义
可重入锁是一种显式锁机制,允许同一线程多次获取同一把锁。每次获取锁时,内部维护一个计数器(hold count),释放锁时计数器递减,直到归零后锁才被完全释放。

特点

  • 支持公平性选择(公平锁按请求顺序分配,非公平锁允许插队)。

  • 提供更灵活的加锁/解锁控制(如tryLock、超时等待)。

  • 可绑定多个条件变量(Condition)。

解决的问题
解决线程因重复获取已持有的锁而导致的死锁,尤其在递归调用或多个方法需要同步访问同一资源时。

Java 示例

ReentrantLock lock = new ReentrantLock();

void methodA() {
    lock.lock();
    try {
        methodB(); // 递归调用
    } finally {
        lock.unlock();
    }
}

void methodB() {
    lock.lock();
    try {
        // 操作共享资源
    } finally {
        lock.unlock();
    }
}

若使用非可重入锁,methodA调用methodB时会因重复获取锁而阻塞;可重入锁则通过计数器正常执行。


3. 可重入 vs 可重入锁
特性 可重入(Reentrant) 可重入锁(Reentrant Lock)
范围 广义概念,适用于函数、代码块等 具体锁实现(如ReentrantLock
核心机制 无锁或隐式同步(如synchronized 显式锁管理(计数器、条件变量)
主要用途 保证代码在多线程/递归中安全执行 显式控制锁的获取与释放,避免死锁
线程安全实现方式 不依赖共享状态或通过原子操作 显式加锁和解锁

4. 总结
  • 可重入
    广义的代码安全特性,确保同一线程可重复进入同步代码,避免因锁自身导致的死锁。例如,Java的synchronized关键字隐式支持可重入。

  • 可重入锁
    具体锁实现(如ReentrantLock),通过计数器显式管理锁的获取次数,提供更灵活的同步控制(如公平性、条件变量),适用于复杂并发场景。

核心价值
两者共同解决了线程因重复获取已持有锁而引发的死锁问题,同时提升了代码的灵活性和安全性,是高并发编程中的关键机制。

你可能感兴趣的:(java)