Java 的 AQS

发布于:2025-05-26 ⋅ 阅读:(44) ⋅ 点赞:(0)

Java中的**AQS(AbstractQueuedSynchronizer)**是并发包java.util.concurrent的核心组件,用于构建锁和同步器的基础框架。许多并发工具(如ReentrantLock、Semaphore、CountDownLatch等)都基于AQS实现。


AQS 核心原理

  1. 状态管理(State)
    通过volatile int state变量表示共享资源的状态(如锁的持有计数、信号量的许可数),通过CAS(Compare-And-Swap)操作保证原子性修改。
  2. CLH队列(线程阻塞队列)
    使用一个FIFO双向队列(CLH锁的变体)管理等待线程。当线程获取资源失败时,会被封装为Node节点加入队列,通过自旋或阻塞等待唤醒。
  3. 两种模式
    • 独占模式(Exclusive):资源仅由一个线程持有(如ReentrantLock)。
    • 共享模式(Shared):资源可被多个线程共享(如Semaphore)。

关键方法

子类需重写以下方法(模板方法模式):

  • 独占模式
    tryAcquire(int arg):尝试获取资源。
    tryRelease(int arg):尝试释放资源。
  • 共享模式
    tryAcquireShared(int arg):尝试获取共享资源。
    tryReleaseShared(int arg):尝试释放共享资源。

AQS提供acquire()release()等模板方法,内部调用上述子类方法,并处理线程排队与唤醒。


AQS 应用示例

非重入锁为例:

public class NonReentrantLock implements Lock {
    private static class Sync extends AbstractQueuedSynchronizer {
        @Override
        protected boolean tryAcquire(int arg) {
            if (compareAndSetState(0, 1)) { // CAS尝试获取锁
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

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

    private final Sync sync = new Sync();

    @Override
    public void lock() {
        sync.acquire(1);
    }

    @Override
    public void unlock() {
        sync.release(1);
    }
    // 其他方法省略...
}

AQS 节点状态

  • CANCELLED (1):线程因超时或中断放弃等待。
  • SIGNAL (-1):当前节点释放资源后需唤醒后继节点。
  • CONDITION (-2):节点在条件队列中等待。
  • PROPAGATE (-3):共享模式下唤醒需传播给后续节点。

优势与场景

  • 灵活性:通过重写少量方法即可实现自定义同步器。
  • 高效性:基于CAS和CLH队列减少竞争开销。
  • 广泛应用:Java并发工具的核心基础。

学习AQS的意义:理解其原理是掌握Java并发编程的关键,尤其在高性能锁设计、线程调度优化等场景中至关重要。


网站公告

今日签到

点亮在社区的每一天
去签到