干货,深入剖析ReentrantLock源码,推荐收藏

ReentrantLock和Synchronized都是Java开发中最常用的锁,与Synchronized这种JVM内置锁不同的是,ReentrantLock提供了更丰富的语义 。可以创建公平锁或非公平锁、响应中断、超时等待、按条件唤醒等 。在某些场景下,使用ReentrantLock更适合,功能更强大 。
前两篇文章,我们分析了AQS的加锁流程、以及源码实现 。当时我们就说了,AQS使用了模板设计模式,父类中定义加锁流程,子类去实现具体的加锁逻辑 。所以大部分加锁代码已经在父类AQS中实现了,导致ReentrantLock的源码非常简单,一块学习一下 。
先看一下ReentrantLock怎么使用?
1. ReentrantLock的使用/** * @author 一灯架构 * @apiNote ReentrantLock示例 **/public class ReentrantLockDemo {public static void main(String[] args) {// 1. 创建ReentrantLock对象ReentrantLock lock = new ReentrantLock();// 2. 加锁lock.lock();try {// 3. 这里执行具体的业务逻辑} finally {// 4. 释放锁lock.unlock();}}}可以看到ReentrantLock的使用非常简单,调用lock加锁,unlock释放锁,需要配置try/finally使用,保证在代码执行出错的时候也能释放锁 。
ReentrantLock也可以配合Condition条件使用,具体可以翻一下前几篇文章中BlockingQueue的源码解析,那里面有ReentrantLock的实际使用 。
再看一下ReentrantLock的类结构
2. ReentrantLock类结构// 实现Lock接口public class ReentrantLock implements Lock {// 只有一个Sync同步变量private final Sync sync;// Sync继承自AQS,主要逻辑都在这里面abstract static class Sync extends AbstractQueuedSynchronizer {}// Sync的两个子类,分别实现了公平锁和非公平锁static final class FairSync extends Sync {}static final class NonfairSync extends Sync {}}可以看出ReentrantLock的类结构非常简单,实现了Lock接口 。
类里面有两个静态内部类,分别实现公平锁和非公平锁 。
看一下Lock接口中,定义了哪些方法?
public interface Lock {// 加锁void lock();// 加可中断的锁void lockInterruptibly() throws InterruptedException;// 尝试加锁boolean tryLock();// 一段时间内,尝试加锁boolean tryLock(long time, TimeUnit unit) throws InterruptedException;// 释放锁void unlock();// 新建条件状态Condition newCondition();}就是一些使用锁的常用方法 。
在上篇文章中浏览AQS源码的时候,了解到AQS定义了一些有关具体加锁、释放锁的抽象方法,留给子类去实现,再看一下有哪些抽象方法:
// 加独占锁protected boolean tryAcquire(int arg) {throw new UnsupportedOperationException();}// 释放独占锁protected boolean tryRelease(int arg) {throw new UnsupportedOperationException();}// 加共享锁protected int tryAcquireShared(int arg) {throw new UnsupportedOperationException();}// 释放共享锁protected boolean tryReleaseShared(int arg) {throw new UnsupportedOperationException();}// 判断是否是当前线程正在持有锁protected boolean isHeldExclusively() {throw new UnsupportedOperationException();}由于ReentrantLock使用的是独占锁,所以只需要实现独占锁相关的方法就可以了 。
3. ReentrantLock源码解析3.1 ReentrantLock构造方法// 默认的构造方法,使用非公平锁public ReentrantLock() {sync = new NonfairSync();}// 传true,可以指定使用公平锁public ReentrantLock(boolean fair) {sync = fair ? new FairSync() : new NonfairSync();}在创建ReentrantLock对象的时候,可以指定使用公平锁还是非公平锁,默认使用非公平锁,显然非公平锁的性能更好 。
先思考一个面试常考问题,公平锁和非公平锁是怎么实现的?
3.2 非公平锁源码先看一下加锁源码:
【干货,深入剖析ReentrantLock源码,推荐收藏】从父类ReentrantLock的加锁方法入口:

经验总结扩展阅读