ReentrantLock实现原理?

ReentrantLock实现原理?
ReentrantLock 是可重入的独占锁,只能有一个线程可以获取该锁,其它获取该锁的线程会被阻塞而被放入该锁的阻塞队列里面。
看看ReentrantLock的加锁操作:
// 创建非公平锁
ReentrantLock lock = new ReentrantLock();
// 获取锁操作
lock.lock();
try {
// 执行代码逻辑
} catch (Exception ex) {
// ...
} finally {
// 解锁操作
lock.unlock();
}
new ReentrantLock()
构造函数默认创建的是非公平锁 NonfairSync。
公平锁 FairSync
- 公平锁是指多个线程按照申请锁的顺序来获取锁,线程直接进入队列中排队,只有队列中的第一个线程才能获得锁。
- 公平锁的优点是等待锁的线程不会被饿死(Starvation)。然而,整体吞吐效率相对于非公平锁要低,因为等待队列中除第一个线程以外的所有线程都会被阻塞,唤醒阻塞线程的开销比非公平锁大。
非公平锁 NonfairSync
- 非公平锁是多个线程在加锁时直接尝试获取锁,如果获取不到,它们才会到等待队列的队尾等待。但是,如果此时锁刚好可用,那么线程可以无需阻塞直接获取到锁。
- 非公平锁的优点是可以减少唤醒线程的开销,整体的吞吐效率更高,因为线程有机会在不阻塞的情况下直接获得锁,CPU无需唤醒所有线程。然而,等待队列中的线程可能会被饿死(Starvation),或者需要等待很长时间才能获得锁。
在默认情况下创建的锁对象(lock()
)时:
- 如果锁当前没有被其他线程占用,并且当前线程之前没有获取过该锁,则当前线程会获取到该锁,将当前线程设置为锁的拥有者,并将AQS的状态值设置为1,然后直接返回。如果当前线程之前已经获取过该锁,则只是简单地将AQS的状态值加1后返回。
- 如果锁已经被其他线程持有,非公平锁会尝试获取锁。如果获取失败,当前线程会被放入AQS队列中阻塞挂起。