其他分享
首页 > 其他分享> > 干货,深入剖析ReentrantLock源码

干货,深入剖析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使用的是独占锁,所以只需要实现独占锁相关的方法就可以了。

标签:ReentrantLock,Synchronized,java,丰富,语义,功能,文章,流程,源码,学习
来源: