有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准
https://blog.zysicyj.top
AQS (AbstractQueuedSynchronizer) 概述
AQS,即 AbstractQueuedSynchronizer,是Java并发包中的一个核心组件,它为实现依赖于先进先出 (FIFO) 等待队列的阻塞锁和相关的同步器(如信号量、事件等)提供了一个框架。
核心概念
AQS 使用一个整型的 volatile 变量(称为 state
)来表示同步状态,并通过内置的 FIFO 队列来管理那些阻塞在同步状态上的线程。
状态(State)
AQS 中的 state
变量是用来表示同步状态的。例如,在一个独占锁的实现中,state
可能表示锁的占用情况(0 表示未锁定,1 表示锁定)。
节点(Node)和队列
当线程尝试获取同步状态失败时,AQS 会将该线程包装成一个节点(Node)并将其加入到队列中。这个队列是一个双向链表,用于实现等待队列。
AQS 的主要方法
AQS 定义了一系列的方法,这些方法可以被同步器实现以提供其独特的同步逻辑。
独占模式
boolean tryAcquire(int arg)
:尝试获取资源,成功则返回true
,失败则返回false
。boolean tryRelease(int arg)
:尝试释放资源,成功则返回true
,失败则返回false
。
共享模式
int tryAcquireShared(int arg)
:尝试获取资源。返回值大于等于0表示成功;小于0表示失败。boolean tryReleaseShared(int arg)
:尝试释放资源,成功则返回true
,失败则返回false
。
模板方法
void acquire(int arg)
:调用tryAcquire
,并在失败时将线程加入队列,可能会阻塞。void release(int arg)
:调用tryRelease
并唤醒等待中的线程。void acquireShared(int arg)
:调用tryAcquireShared
,并在失败时将线程加入队列,可能会阻塞。void releaseShared(int arg)
:调用tryReleaseShared
并唤醒等待中的线程。
AQS 的重要性
AQS 的设计极大地简化了同步控制的实现,许多并发工具类都是基于 AQS 构建的,例如:
ReentrantLock
:一个可重入的互斥锁。CountDownLatch
:一个允许一个或多个线程等待一系列指定操作的完成。Semaphore
:一个计数信号量。FutureTask
:一个可取消的异步计算。
AQS 的使用示例
以下是一个简化的 AQS 使用示例,展示了如何实现一个独占锁:
代码语言:javascript复制class Mutex extends AbstractQueuedSynchronizer {
// 尝试获取锁
protected boolean tryAcquire(int acquires) {
assert acquires == 1; // Otherwise unused
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
// 尝试释放锁
protected boolean tryRelease(int releases) {
assert releases == 1; // Otherwise unused
if (getState() == 0) throw new IllegalMonitorStateException();
setExclusiveOwnerThread(null);
setState(0);
return true;
}
// 是否锁定状态
public boolean isLocked() {
return getState() != 0;
}
}
在这个示例中,tryAcquire
方法检查 state
是否为0,如果是,则尝试将其设置为1,如果设置成功,则表示获取了锁。tryRelease
方法将 state
设置回0,并清除独占线程。
AQS 提供的模板方法 acquire
和 release
会调用这些方法,并在必要时进行线程的排队和唤醒。
总结
AQS 是 Java 并发编程中的一个重要组件,它通过内部的同步状态、等待队列和模板方法,为构建锁和其他同步器提供了强大的基础。理解和掌握 AQS 对于深入学习 Java 并发编程至关重要。
本文由博客一文多发平台 OpenWrite 发布!