重入锁 ReentrantLock 原理

类结构

public class ReentrantLock implements Lock, java.io.Serializable {
 
    // 有个 Sync 的属性(是内部类 Sync,就是 AQS)
    private final Sync sync;
    // Sync 继承 AQS
    abstract static class Sync extends AbstractQueuedSynchronizer
    // 非公平锁
    static final class NonfairSync extends Sync;
    // 公平锁
    static final class FairSync extends Sync;
    // 默认创建非公平锁
    public ReentrantLock() {
        sync = new NonfairSync();
    }
    // 可以指定创建公平还是非公平锁
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }
    // 获取锁,底层是通过 Sync 实现的
    public void lock() {
        sync.lock();
    }
    // 释放锁,也是通过 Sync 实现的
    public void unlock() {
        sync.release(1);
    }
    
}

公平锁

// java.util.concurrent.locks.ReentrantLock.FairSync#lock
final void lock() {
    acquire(1);
}

// java.util.concurrent.locks.AbstractQueuedSynchronizer#acquire
public final void acquire(int arg) {
    if (!tryAcquire(arg) &&
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}

//java.util.concurrent.locks.AbstractQueuedSynchronizer#tryAcquire
protected boolean tryAcquire(int arg) {
    throw new UnsupportedOperationException();
}

// java.util.concurrent.locks.ReentrantLock.FairSync#tryAcquire
protected final boolean tryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState(); // 资源状态
    if (c == 0) { // 如果是0,表示当前没有别的线程获取
        if (!hasQueuedPredecessors() && // AQS 的方法,看当前队列是否已经有节点了,如果没有才尝试获取锁,不然乖乖排队。非公平锁不会有这个判断
            compareAndSetState(0, acquires) // 尝试获取锁
           ) { 
            setExclusiveOwnerThread(current);
            return true;
        }
    }
    else if (current == getExclusiveOwnerThread()) { // 如果 state != 0,看看持有锁的线程是不是当前线程,重入锁的体现
        int nextc = c + acquires; // state +1,state >0 说明锁被持有,并且被重复持有,重入
        if (nextc < 0)
            throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;
    }
    return false;
}

非公平锁

// java.util.concurrent.locks.ReentrantLock.NonfairSync#lock
final void lock() {
    if (compareAndSetState(0, 1)) // 资源状态改成 1,非公平锁一进来就尝试抢锁
        setExclusiveOwnerThread(Thread.currentThread());
    else
        acquire(1);
}

// java.util.concurrent.locks.AbstractQueuedSynchronizer#acquire
public final void acquire(int arg) {
    if (!tryAcquire(arg) &&
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}

// java.util.concurrent.locks.AbstractQueuedSynchronizer#tryAcquire
protected boolean tryAcquire(int arg) {
    throw new UnsupportedOperationException();
}

// java.util.concurrent.locks.ReentrantLock.NonfairSync#tryAcquire
protected final boolean tryAcquire(int acquires) {
    return nonfairTryAcquire(acquires);
}

// java.util.concurrent.locks.ReentrantLock.Sync#nonfairTryAcquire
final boolean nonfairTryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) {
        if (compareAndSetState(0, acquires)) { // 非重入锁没有判断队列是否有节点,直接尝试获取锁
            setExclusiveOwnerThread(current);
            return true;
        }
    }
    else if (current == getExclusiveOwnerThread()) {
        int nextc = c + acquires;
        if (nextc < 0) // overflow
            throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;
    }
    return false;
}

要是有 AQS 的知识,分析 ReentrantLock 还是非常容易的,AQS 在上一篇文章中

看得出来公平和非公平锁的唯一区别就是,非公平锁要插队(插队两次)

释放锁

锁的释放也是依赖 Sync 实现的,也是比较简单的,就是维护 state

没有维护队列,释放锁后当前线程的节点要出队,队列的维护是 AQS 实现的

protected final boolean tryRelease(int releases) {
    int c = getState() - releases;
    if (Thread.currentThread() != getExclusiveOwnerThread())
        throw new IllegalMonitorStateException();
    boolean free = false;
    if (c == 0) {
        free = true;
        setExclusiveOwnerThread(null);
    }
    setState(c);
    return free;
}
posted @   CyrusHuang  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示