Java并发编程之AQS原理

一、AQS 组成

1. 同步状态(state
  • 作用:表示资源的可用状态(如锁的持有次数、信号量的许可数量等)。
  • 操作:通过 volatile + CAS(compareAndSetState)保证原子性。
  • 示例
    • ReentrantLockstate=0 表示未锁定,state>0 表示锁定次数。
    • Semaphorestate 表示剩余许可数量。
2. 等待队列
  • 结构:双向链表,每个节点封装一个等待线程。
  • 节点状态
    • CANCELLED:线程已取消等待。
    • SIGNAL:当前节点释放资源后需唤醒后继节点。
    • CONDITION:节点在条件队列中等待。
    • PROPAGATE:共享模式下传播唤醒。

二、AQS 的两种模式

1. 独占模式(Exclusive)
  • 特点:同一时刻仅一个线程可获取资源(如 ReentrantLock)。
  • 关键方法
    • acquire(int arg):获取资源(不可中断)。
    • acquireInterruptibly(int arg):可中断获取。
    • tryAcquire(int arg):需子类实现(定义资源获取逻辑)。
    • release(int arg):释放资源,唤醒后继线程。
2. 共享模式(Shared)
  • 特点:多个线程可同时获取资源(如 SemaphoreCountDownLatch)。
  • 关键方法
    • acquireShared(int arg):获取共享资源。
    • tryAcquireShared(int arg):需子类实现。
    • releaseShared(int arg):释放资源并唤醒等待线程。

三、AQS 工作流程(以独占模式为例)

1. 线程获取资源(acquire
public final void acquire(int arg) {
    if (!tryAcquire(arg) &&           // 尝试直接获取资源
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) // 失败则入队阻塞
        selfInterrupt();              // 恢复中断状态
}
  • 步骤
    1. 尝试获取资源:调用子类实现的 tryAcquire
    2. 入队等待:若失败,将线程封装为 Node 加入队列尾部。
    3. 阻塞线程:通过 LockSupport.park() 挂起线程,等待唤醒。
2. 线程释放资源(release
public final boolean release(int arg) {
    if (tryRelease(arg)) {            // 子类实现释放逻辑
        Node h = head;
        if (h != null && h.waitStatus != 0)
            unparkSuccessor(h);       // 唤醒后继节点线程
        return true;
    }
    return false;
}
  • 步骤
    1. 释放资源:调用子类实现的 tryRelease
    2. 唤醒后继:找到队列中第一个未取消的节点,通过 LockSupport.unpark() 唤醒线程。

四、AQS 的条件变量(Condition

通过 ConditionObject 实现类似 wait/notify 的等待/通知机制:

  • 条件队列:每个 Condition 维护一个单向链表队列。
  • 关键方法
    • await():释放锁并加入条件队列。
    • signal():将条件队列中的节点转移到同步队列,等待获取锁。

五、AQS 的应用示例

1. 实现不可重入锁
class Mutex implements Lock {
    private final Sync sync = new Sync();

    static class Sync extends AbstractQueuedSynchronizer {
        protected boolean tryAcquire(int arg) {
            if (compareAndSetState(0, 1)) { // state=0 表示未锁定
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

        protected boolean tryRelease(int arg) {
            if (getState() == 0) throw new IllegalMonitorStateException();
            setExclusiveOwnerThread(null);
            setState(0); // 释放锁
            return true;
        }
    }

    // 其他 Lock 接口方法委托给 sync
    public void lock() { sync.acquire(1); }
    public void unlock() { sync.release(1); }
    // ...
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值