可重入锁在 AQS 中如何实现?
                           
天天向上
发布: 2025-07-20 10:44:39

原创
628 人浏览过

可重入锁(ReentrantLock)在 AQS(AbstractQueuedSynchronizer)中的实现是 Java 并发编程中的核心机制之一。

下面从实际结构、可重入原理、核心方法、源码片段、内存语义等多个层面,深入剖析:


一、背景知识简述

什么是 AQS?

AQS,全称 AbstractQueuedSynchronizer,是 J.U.C(java.util.concurrent)包中的基础同步框架:

它基于一个 volatile 的 int 状态变量(state)和一个 FIFO 队列,实现各种锁与同步器的基础,比如:

  • ReentrantLock
  • CountDownLatch
  • Semaphore
  • ReentrantReadWriteLock

二、什么是可重入?

可重入(Reentrancy)是指:

同一线程可以重复获取同一把锁,不被阻塞。

如:

lock.lock();   // 第一次加锁
lock.lock();   // 第二次加锁:不阻塞
...
lock.unlock(); // 释放一次
lock.unlock(); // 真正释放

三、可重入锁的关键点(ReentrantLock 依赖 AQS)

关键点实现细节
锁状态计数state 表示锁的持有状态(加锁次数)
锁持有者记录exclusiveOwnerThread 表示当前持有锁的线程
可重入判断如果当前线程再次获取锁,允许加锁、state++
解锁机制每次 unlock()state--,直到 state==0 才释放锁

四、源码深度解析:如何实现可重入

源码位置:

  • ReentrantLock.java(封装接口)
  • AbstractQueuedSynchronizer.java(核心逻辑)

1. lock() 加锁逻辑:可重入判断

public final void acquire(int arg) {
    if (!tryAcquire(arg) &&
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}

2. tryAcquire() 实现可重入逻辑

protected final boolean tryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) {
        // 如果没人持有锁,尝试获取(用 CAS)
        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;
}

同一个线程再次进来,不再排队,直接累加 state


3. unlock() 解锁逻辑:逐层释放

public final boolean release(int arg) {
    if (tryRelease(arg)) {
        Node h = head;
        if (h != null && h.waitStatus != 0)
            unparkSuccessor(h);
        return true;
    }
    return false;
}

4. tryRelease():state–,只有为0才真正释放锁

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); // 🔁 可重入对应的 state 次数
    return free;
}

五、线程调度模型图解

Thread-A    ── lock() → state=1
            ── lock() → state=2(可重入)

Thread-A    ── unlock() → state=1
            ── unlock() → state=0 → 唤醒下一个线程

六、底层核心机制

机制说明
CAS比较并交换 state,原子更新状态
volatilestate 是 volatile,确保多线程下的可见性
自旋队列AQS 中的等待线程用双向链表(CLH 队列)管理
内存语义acquirerelease 封装了内存屏障

七、源码与参考资料


总结一句话

AQS 中可重入锁通过:state 计数 + 当前线程判断 + CAS 原子操作 实现线程的多次加锁和对应解锁。


更多详细内容请关注其他相关文章!

发表回复 0

Your email address will not be published. Required fields are marked *