1.基本概念:
可重入锁(Reentrant Lock),又称递归锁(Recursive Lock),是一种在多线程编程中使用的锁机制。它允许同一个线程在持有锁的情况下再次获取它,而不会引起死锁。这在处理递归方法或需要重复进入同步代码块的场景下非常有用。
2.特点:
(1).可重入性:如果一个线程已经获得了锁,再次请求该锁时不会被阻塞,而是允许其成功获取锁并进入同步代码块。这意味着同一个线程可以多次进入锁保护的代码块。
(2).计数器机制:可重入锁内部通常维护一个计数器,记录当前线程获取锁的次数。每次锁被获取时,计数器加一;每次锁被释放时,计数器减一。当计数器归零时,锁才真正被释放。
(3).公平性选项:许多可重入锁实现允许设置“公平”策略,按请求锁的顺序(FIFO)分配锁。非公平锁通常会更高效,因为它减少了上下文切换的次数,但可能导致线程饥饿。
3. 与普通锁的区别:
- 普通锁(如 Java 的
synchronized
):一个线程获得锁后,其他线程尝试获取同一个锁时会被阻塞,即使是同一个线程也不能再次进入同步代码块。- 可重入锁:同一个线程可以多次获得同一把锁,不会阻塞自己,但其他线程仍会被阻塞。
4.可重入锁适用于以下场景:
- 递归方法调用:一个持有锁的方法调用另一个持有相同锁的方法,如果没有可重入锁,线程会被阻塞。
- 分段操作需要持有锁:在复杂的多线程环境中,一个方法可能会分多个步骤操作共享资源,这时可重入锁能防止出现死锁情况。
5.示例:
java">import java.util.concurrent.locks.ReentrantLock;public class ReentrantLockExample {private final ReentrantLock lock = new ReentrantLock();public void outerMethod() {lock.lock(); // 获取锁try {System.out.println("Outer method executing...");innerMethod(); // 调用内层方法} finally {lock.unlock(); // 释放锁}}public void innerMethod() {lock.lock(); // 线程可以再次获取同一把锁try {System.out.println("Inner method executing...");} finally {lock.unlock(); // 释放锁}}public static void main(String[] args) {ReentrantLockExample example = new ReentrantLockExample();example.outerMethod();}
}
在这个示例中,outerMethod()
和 innerMethod()
都在同一线程中调用,同一线程可以多次获取同一把锁。
6.优缺点:
6.1优点:
(1).解决递归调用或同一线程需要多次进入同步代码块的问题。
(2).可以实现公平锁,避免线程饥饿。
6.1缺点:
(1).相比于 synchronized
,使用更复杂且容易出错(需要显式获取和释放锁)。
(2).使用不当可能导致死锁。
7.可重入锁的主要解决的问题是:
- 递归调用中的死锁问题:允许同一个线程多次获取同一把锁。
- 在多个方法之间共享锁的场景:保持线程在不同方法调用中对同一资源的控制。
- 更灵活的锁管理:支持可中断的锁获取和公平锁策略。