有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准
https://blog.zysicyj.top
全网最细面试题手册,支持艾宾浩斯记忆法。这是一份最全面、最详细、最高质量的 java面试题,不建议你死记硬背,只要每天复习一遍,有个大概印象就行了。 https://store.amazingmemo.com/chapterDetail/1685324709017001`
AQS,即 AbstractQueuedSynchronizer,是Java并发包中的一个核心组件,它为实现依赖于先进先出 (FIFO) 等待队列的阻塞锁和相关的同步器(如信号量、事件等)提供了一个框架。
AQS 使用一个整型的 volatile 变量(称为 state
)来表示同步状态,并通过内置的 FIFO 队列来管理那些阻塞在同步状态上的线程。
AQS 中的 state
变量是用来表示同步状态的。例如,在一个独占锁的实现中,state
可能表示锁的占用情况(0 表示未锁定,1 表示锁定)。
当线程尝试获取同步状态失败时,AQS 会将该线程包装成一个节点(Node)并将其加入到队列中。这个队列是一个双向链表,用于实现等待队列。
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 构建的,例如:
ReentrantLock
:一个可重入的互斥锁。CountDownLatch
:一个允许一个或多个线程等待一系列指定操作的完成。Semaphore
:一个计数信号量。FutureTask
:一个可取消的异步计算。以下是一个简化的 AQS 使用示例,展示了如何实现一个独占锁:
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 并发编程至关重要。