AQS介绍

AQS的全称为(AbstractQueuedSynchronizer),这个类在java.util.concurrent.locks包下面。

AQS核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制AQS是用CLH队列锁实现的,即将暂时获取不到锁的线程加入到队列中。

 

AQS使用一个int成员变量来表示同步状态,通过内置的FIFO队列来完成获取资源线程的排队工作。AQS使用CAS对该同步状态进行原子操作实现对其值的修改。

private volatile int state;//共享变量,使用volatile修饰保证线程可见性

状态信息通过protected类型的getState,setState,compareAndSetState进行操作

//返回同步状态的当前值
protected final int getState() {  
        return state;
}
 // 设置同步状态的值
protected final void setState(int newState) { 
        state = newState;
}
//原子地(CAS操作)将同步状态值设置为给定值update如果当前同步状态的值等于expect(期望值)
protected final boolean compareAndSetState(int expect, int update) {
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}

AQS定义两种资源共享方式

  • Exclusive(独占):只有一个线程能执行,如ReentrantLock。又可分为公平锁和非公平锁:
    • 公平锁:按照线程在队列中的排队顺序,先到者先拿到锁
    • 非公平锁:当线程要获取锁时,无视队列顺序直接去抢锁,谁抢到就是谁的
  • Share(共享):多个线程可同时执行,如Semaphore/CountDownLatch。Semaphore、CountDownLatCh、 CyclicBarrier、ReadWriteLock
  • 转自github高星的javaGuide文章,感谢
### AQS(AbstractQueuedSynchronizer)原理与作用 #### 简介 `AbstractQueuedSynchronizer`(简称 AQS)是 Java 并发包 `java.util.concurrent` 中的核心类之一,为构建同步组件提供了一个基础框架。它通过维护一个同步状态变量和一个等待队列来实现线程的阻塞与唤醒机制,从而支持多种并发控制策略,如独占锁、共享锁等 [^2]。 AQS 的核心设计思想是基于模板方法模式,定义了资源获取和释放的基本流程,并将具体的逻辑交由子类实现。这种结构使得开发者可以专注于业务逻辑的定制,而无需关心底层复杂的线程排队、状态变更等细节 [^4]。 #### 核心机制 ##### 同步状态管理 AQS 通过一个 `volatile int state` 变量来表示同步状态。该状态可以通过以下三个受保护的方法进行操作: - `getState()`:获取当前同步状态。 - `setState(int newState)`:设置同步状态。 - `compareAndSetState(int expect, int update)`:使用 CAS 操作原子性地更新状态。 这些方法确保了状态在多线程环境下的可见性和一致性 [^3]。 ##### 等待队列(CLH 队列) AQS 内部维护了一个 FIFO 的双向链表,称为 CLH 队列(Craig-Landin-Hagersten Queue)。当线程尝试获取资源失败时,会被封装成一个 Node 节点并加入到队列中等待;当资源被释放后,AQS 会通知队列中的下一个节点去尝试获取资源 [^5]。 每个节点的状态由 `waitStatus` 字段表示,常见的状态包括: - `CANCELLED`:表示该节点已取消。 - `SIGNAL`:表示后续节点需要被唤醒。 - `CONDITION`:用于条件等待。 - `PROPAGATE`:用于共享模式传播。 ##### 独占与共享模式 AQS 支持两种基本的同步模式: 1. **独占模式**(Exclusive Mode) 在该模式下,一次只能有一个线程持有资源。例如 `ReentrantLock` 就是典型的独占同步器。子类需重写以下方法: - `tryAcquire(int arg)`:尝试以独占方式获取资源。 - `tryRelease(int arg)`:尝试以独占方式释放资源 [^4]。 2. **共享模式**(Shared Mode) 在该模式下,多个线程可以同时持有资源。例如 `CountDownLatch` 和 `Semaphore` 使用的就是共享模式。子类需重写以下方法: - `tryAcquireShared(int arg)`:尝试以共享方式获取资源。 - `tryReleaseShared(int arg)`:尝试以共享方式释放资源 [^3]。 #### 典型应用 AQS 是许多并发工具类的基础实现,包括但不限于: - **ReentrantLock**:可重入的互斥锁,支持公平与非公平模式。 - **Semaphore**:信号量,用于控制对有限资源池的访问。 - **CountDownLatch**:倒计数门闩,用于协调多个线程的启动或完成。 - **CyclicBarrier**:循环屏障,允许多个线程彼此等待到达某个公共屏障点 [^2]。 这些同步器都通过继承 AQS 并实现其抽象方法,定义了各自的同步语义。 #### 示例代码:自定义一个简单的独占锁 ```java import java.util.concurrent.locks.AbstractQueuedSynchronizer; import java.util.concurrent.locks.Lock; public class SimpleAQSLock implements Lock { private final Sync sync = new Sync(); private static class Sync extends AbstractQueuedSynchronizer { @Override protected boolean tryAcquire(int acquires) { if (compareAndSetState(0, 1)) { setExclusiveOwnerThread(Thread.currentThread()); return true; } return false; } @Override protected boolean tryRelease(int releases) { if (getState() == 0) throw new IllegalMonitorStateException(); setState(getState() - 1); if (getState() == 0) setExclusiveOwnerThread(null); return true; } @Override protected boolean isHeldExclusively() { return getState() == 1 && getExclusiveOwnerThread() == Thread.currentThread(); } } @Override public void lock() { sync.acquire(1); } @Override public void lockInterruptibly() throws InterruptedException { sync.acquireInterruptibly(1); } @Override public boolean tryLock() { return sync.tryAcquire(1); } @Override public boolean tryLock(long time, java.util.concurrent.TimeUnit unit) throws InterruptedException { return sync.tryAcquireNanos(1, unit.toNanos(time)); } @Override public void unlock() { sync.release(1); } @Override public java.util.concurrent.locks.Condition newCondition() { return sync.newCondition(); } } ``` 上述示例展示了如何通过继承 AQS 实现一个简单的独占锁。其中 `tryAcquire` 和 `tryRelease` 方法分别用于控制资源的获取与释放,`setExclusiveOwnerThread` 和 `getExclusiveOwnerThread` 用于记录当前持有锁的线程 [^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值