ReentrantLock 底层实现:
ReentrantLock
是 Java 中提供的一种高级的线程同步机制,其底层实现涉及到多个概念和数据结构。
1. 可中断性:
ReentrantLock
实现了可中断性,这意味着线程在等待锁的过程中,可以被其他线程中断而提前结束等待。在底层,ReentrantLock
使用了与 LockSupport.park()
和 LockSupport.unpark()
相关的机制来实现可中断性。
2. 设置超时时间:
ReentrantLock
支持在尝试获取锁时设置超时时间,即等待一定时间后如果还未获得锁,则放弃锁的获取。这是通过内部的 tryAcquireNanos
方法来实现的。
3. 公平锁和非公平锁:
在直接创建 ReentrantLock
对象时,默认情况下是非公平锁。公平锁是按照线程等待的顺序来获取锁,而非公平锁则允许多个线程在同一时刻竞争锁,不考虑它们申请锁的顺序。公平锁可以通过在创建 ReentrantLock
时传入 true
来设置,例如:
ReentrantLock fairLock = new ReentrantLock(true);
4. 多个条件变量:
ReentrantLock
支持多个条件变量,每个条件变量可以与一个 ReentrantLock
关联。这使得线程可以更灵活地进行等待和唤醒操作,而不仅仅是基于对象监视器的 wait()
和 notify()
。多个条件变量的实现依赖于 Condition
接口,例如:
ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();
// 使用下面方法进行等待和唤醒
condition.await();
condition.signal();
5. 可重入性:
ReentrantLock
支持可重入性,即同一个线程可以多次获得同一把锁,而不会造成死锁。这是通过内部的 holdCount
计数来实现的。当一个线程多次获取锁时,holdCount
递增,释放锁时递减,只有当 holdCount
为零时,其他线程才有机会获取锁。
底层机制:
ReentrantLock
的底层实现主要依赖于 AbstractQueuedSynchronizer
(AQS)这个抽象类。AQS 是一个提供了基本同步机制的框架,其中包括了队列、状态值等。ReentrantLock
在 AQS 的基础上通过内部类 Sync
来实现具体的锁操作。不同的 Sync
子类实现了公平锁和非公平锁的不同逻辑。
总体而言,ReentrantLock
是一个功能强大且灵活的锁,其底层实现借助了 Java 并发包提供的底层机制,如 AQS、LockSupport 等。这些机制使得 ReentrantLock
能够提供多种高级的同步功能。
应用场景:
可重入锁的主要应用场景是在需要同步控制多个层次的嵌套代码执行时,以及递归调用中需要多次获得同一把锁的情况。这种锁的特性使得同一个线程在获取锁的时候不会被阻塞,而是能够继续获取相同的锁,从而避免了死锁的发生。
-
递归调用: 当一个方法递归地调用自身,而这个方法在执行过程中需要获取某个锁时,可重入锁就能够确保同一个线程在递归调用中能够多次获得同一把锁,而不会被阻塞。
-
嵌套的同步代码块: 当一个方法中包含多个同步代码块,并且这些同步代码块之间存在嵌套关系时,可重入锁能够确保同一个线程在嵌套执行过程中能够多次获得同一把锁。
-
锁的可重入性: 在一个类的多个方法中使用同一把锁,而这些方法之间存在调用关系时,可重入锁能够确保同一个线程在不同方法中能够多次获得同一把锁。