AbstractQueuedSynchronizer(AQS)是 Java 中的一个同步框架,它提供了一种实现同步器的基础框架,用于构建锁和同步工具类。
一、AQS 的核心组成部分
-
状态变量(state):
- AQS 使用一个整数类型的变量来表示同步状态。不同的同步器可以根据自己的需求解释这个状态变量的含义。
- 例如,在独占锁中,这个状态变量可以表示锁是否被占用;在共享锁中,它可以表示共享资源的可用数量。
-
等待队列(CLH 队列):
- AQS 维护了一个等待队列,用于存储等待获取同步状态的线程。
- 当一个线程尝试获取同步状态失败时,它会被封装成一个节点加入到等待队列中,并进入等待状态。当同步状态可用时,等待队列中的头节点会被唤醒,尝试获取同步状态。
二、AQS 的工作原理
-
获取同步状态:
- 当一个线程调用同步器的获取方法时,AQS 会首先检查同步状态是否可用。如果可用,线程会获取同步状态并继续执行;如果不可用,线程会被加入到等待队列中,并进入等待状态。
- 在独占模式下,只有一个线程可以获取同步状态;在共享模式下,多个线程可以同时获取同步状态。
-
释放同步状态:
- 当一个线程调用同步器的释放方法时,AQS 会更新同步状态,并检查等待队列中是否有等待的线程。如果有,会唤醒等待队列中的头节点,让它尝试获取同步状态。
三、AQS 的应用场景
-
构建锁:
- Java 中的 ReentrantLock 和 ReentrantReadWriteLock 都是基于 AQS 实现的。
- ReentrantLock 是一个独占锁,它允许多个线程同时竞争锁,只有一个线程能够获取锁,其他线程会被阻塞。
- ReentrantReadWriteLock 是一个读写锁,它允许多个线程同时读取共享资源,但在写入资源时需要独占锁。
-
构建同步工具类:
- Java 中的 CountDownLatch、Semaphore 和 CyclicBarrier 等同步工具类也是基于 AQS 实现的。
- CountDownLatch 用于等待多个线程完成任务后再继续执行。
- Semaphore 用于控制同时访问共享资源的线程数量。
- CyclicBarrier 用于等待多个线程到达一个同步点后再一起继续执行。
四、AQS 的优势
-
提供了一种统一的同步框架:
- AQS 为构建各种同步器提供了一种统一的框架,使得开发人员可以更加方便地实现自己的同步器。
-
高效的等待队列管理:
- AQS 使用 CLH 队列来管理等待线程,这种队列具有高效的插入和删除操作,可以快速地将线程加入到等待队列中或从等待队列中唤醒。
-
可扩展性强:
- AQS 提供了一些钩子方法,允许开发人员在同步器的获取和释放同步状态时进行自定义的操作,从而实现更加灵活的同步器。