目录
- 什么是AQS
- 原理
什么是AQS
juc包的结构如下图:
AQS就是AbstractQueuedSynchronizer
,是个抽象类,实现了自己的一些方法。它是阻塞式锁和相关的同步器工具的框架。很多并发类都是基于它实现的,如:ReentrantLock、CountDownLatch、Semaphore、ReadWriteLock,CyclicBarrier。
AQS的设计是基于模板方法模式的,也就是说,使用者需要继承同步器并重写指定的方法,随后将同步器组合在自定义同步组件的实现中,并调用同步器提供的模板方法,而这些模板方法将会调用使用者重写的方法,这样就大大降低了实现一个可靠自定义同步组件的门槛。
子类主要实现以下抽象方法:
- tryAcquire:独占方式获取锁
- tryRelease:独占方式释放锁
- tryAcquireShared:共享方式获取锁
- tryReleaseShared:共享方式释放锁
- isHeldExclusively:该线程是否正在独占资源
原理
- 状态管理
AQS内部通过一个整型变量来表示同步状态,用于标识资源是否被占用或者线程是否可以获取资源。通常情况下,状态为0表示资源未被占用,大于0表示资源已被占用,小于0表示资源已被占用且有等待线程。
- 队列管理
AQS使用一个FIFO队列来管理等待获取资源的线程。AQS提供了一些方法(如enq、addWaiter和unparkSuccessor)来操作队列。
当前线程获取同步状态失败时,同步器会将当前线程以及等待状态等信息构造成为一个节点(Node)并将其加入同步队列,同时会阻塞当前线程,当同步状态释放时,会把首节点中的线程唤醒,使其再次尝试获取同步状态。节点(Node)用来保存获取同步状态失败的线程引用、等待状态以及前驱和后继节点。同步队列的基本结构如图所示:
- acquire方法
acquire方法是AQS的核心方法之一,用于实现线程对资源的获取。当线程调用acquire方法时,AQS首先会通过尝试CAS(Compare and Set)操作来竞争资源。如果成功获取资源,则线程可以继续执行;否则,线程将被加入到等待队列中,进入阻塞状态,直到资源被释放。
-
release方法
release方法是AQS的另一个核心方法,用于实现线程对资源的释放。当线程调用release方法时,AQS会先将同步状态更新为0,然后尝试唤醒等待队列中的其他线程,使它们有机会重新竞争资源。
-
共享模式和独占模式
AQS支持两种同步模式:独占模式和共享模式。独占模式表示同一时间只能有一个线程持有资源,而共享模式则允许多个线程同时持有资源。AQS提供了对应的acquire和release方法来支持这两种模式,并且可以在不同的同步器中灵活地选择使用。