AQS
AQS是一种提供了原子式管理同步状态、阻塞和唤醒线程功能以及队列模型的简单框架。
组成
共享资源状态维护state。
AQS使用一个
volatile
修饰的 int 成员变量来表示同步状态,这个状态可以反映锁的当前持有情况。例如,当状态为 0 时表示无锁状态,而当状态为非零时表示有锁被占用。
FIFO 队列实现线程排队。
AQS维护了一个FIFO(先入先出)的双向队列,用于管理等待获取锁的线程,当一个线程尝试获取锁但失败时,它会进入这个队列并阻塞,直到锁被释放。
CAS操作实现同步状态修改。
AQS使用 compareAndSetState 方法进行原子操作来修改同步状态,这个方法通过循环CAS操作来确保对状态变量的更新,如果更新成功,则表示操作成功,否则会重新尝试。
AQS使用一个Volatile的int类型的成员变量来表示同步状态,通过内置的FIFO队列来完成资源获取的排队工作,通过CAS完成对State值的修改。
AQS应用
独占锁和共享锁模式
AQS支持独占锁和共享锁两种模式,独占锁模式下,每次只有一个线程可以获取锁,而共享锁模式下,允许多个线程同时获取锁。
条件队列和信号量
AQS还支持条件队列和信号量等同步机制,这些机制允许线程在等待某些条件(如锁被释放)时阻塞,并在满足条件时被唤醒
JUC中的应用场景
除了上边 ReentrantLock 的可重入性的应用,AQS 作为并发编程的框架,为很多其他同步工具提供了良好的解决方案。下面列出了JUC中的几种同步工具,大体介绍一下AQS的应用场景:
同步工具 | 同步工具与AQS的关联 |
---|---|
ReentrantLock | 使用AQS保存锁重复持有的次数。当一个线程获取锁时,ReentrantLock记录当前获得锁的线程标识,用于检测是否重复获取,以及错误线程试图解锁操作时异常情况的处理。 |
Semaphore | 使用AQS同步状态来保存信号量的当前计数。tryRelease会增加计数,acquireShared会减少计数。 |
CountDownLatch | 使用AQS同步状态来表示计数。计数为0时,所有的Acquire操作(CountDownLatch的await方法)才可以通过。 |
ReentrantReadWriteLock | 使用AQS同步状态中的16位保存写锁持有的次数,剩下的16位用于保存读锁的持有次数。 |
ThreadPoolExecutor | Worker利用AQS同步状态实现对独占线程变量的设置(tryAcquire和tryRelease)。 |
自定义同步器在实现时只需要实现共享资源 state 的获取与释放方式即可,至于具体线程等待队列的维护(如获取资源失败入队/唤醒出队等),AQS已经在顶层实现好了。