AbstractQueuedSynchronizer简介
队列同步器AbstractQueuedSynchronizer(以下简称同步器或AQS),是用来构建锁或者其他同步组件的基础框架,它使用了一个内置的int成员变量表示同步状态,通过内置的FIFO队列来完成资源获取线程的排队工作。
同步器的主要使用方式是继承,子类通过继承同步器并实现它的抽象方法来管理同步状态,在抽象方法的实现过程中免不了要对同步状态进行更改,这就是需要使用同步器提供的3个方法:getState()、setState(int)和compareAndSetState(int, int)来进行操作,因为它们能够保证状态的改变是安全的。子类推荐被定义为自定义同步组件的静态内部类,同步器自身没有实现任何同步接口,它仅仅是定义了若干同步状态获取和释放的方法,来供自定义同步组件使用,同步器既支持独占式地获取同步状态,也支持共享式地获取同步状态,可以很方便地实现不同类型的同步组件(如ReentrantLock、ReentrantReadWriteLock和CountDownLatch等)。
同步器的接口
同步器的设计是基于模板方法模式的,也就是说,使用者需要继承同步器并重写指定的方法,随后将同步器组合在自定义同步组件的实现中,并调用同步器提供的模板方法,而这些模板方法会调用使用者重写的方法。
重写同步器指定的方法时,需要使用同步器提供的如下3个方法来访问或修改同步状态:
- getState():获取当前同步状态;
- setState(int):设置当前同步状态;
- compareAndSetState(int, int):使用CAS来设置当前状态,该方法能够保证状态设置的原子性。
同步器可重写的方法与描述如下所示(这些方法的默认实现都是直接抛出了UnsupportedOperationException异常):
方法名称 |
描 述 |
protected boolean tryAcquire(int arg) |
独占式地获取同步状态,实现该方法需要查询当前状态并判断当前状态是否符合预期,然后再进行CAS设置同步状态 |
protected boolean tryRelease(int arg) |
独占式释放同步状态,等待获取同步状态的线程将有机会获取同步状态 |
protected int tryAcquireShared(int arg) |
共享式获取同步状态,返回大于等于0的值,表示获取成功,反之,获取失败 |
protected boolean tryReleaseShared(int arg) |
共享式释放同步状态 |
protected boolean isHeldExclusively() |
当前同步器是否在独占模式下被线程占用,一般该方法表示是否被当前线程所独占 |
实现自定义同步组件时,将会调用同步器提供的模板方法,部分模板方法与描述如下:
方法名称 |
描 述 |
void acquire(int arg) |
独占式获取同步状态,如果当前线程获取同步状态成功,则由该方法返回,否则,将会进入同步队列等待,该方法将会调用可重写的tryAcquire(int arg)方法 |
void acquireInterruptibly(int arg) |
与acquire(int arg)相同,但是该方法响应中断,当前线程为获取到同步状态而进入到同步队列中,如果当前线程被中断,则该方法会抛出InterruptedException异常并返回 |
boolean tryAcquireNanos(int arg,long nanos) |
超时获取同步状态,如果当前线程在nanos时间内没有获取到同步状态,那么将会返回false,已经获取则返回true |
void acquireShared(int arg) |
共享式获取同步状态,如果当前线程未获取到同步状态,将会进入同步队列等待,与独占式的主要区别是在同一时刻可以有多个线程获取到同步状态 |
void acquireSharedInterruptibly(int arg) |
与acquireShared(int arg)相同,该方法相应中断 |
boolean tryAcquireSharedNanos(int arg, long nanosTimeout) |
在acquireSharedInterruptibly(int arg)的基础上,增加了超时限制 |
boolean release(int arg) |
独占式释放同步状态,该方法会在释放同步状态之后,将同步队列中第一个节点包含的线程唤醒 |
Boolean releaseShared(int arg) |
共享式释放同步状态 |
Collection<Thread> getQueuedThreads() |
获取等待在同步队列上的线程集合 |
同步器提供的模板方法基本上分为三类:独占式获取与释放同步状态、共享式获取与释放同步状态和查询同步队列中的等待线程情况,自定义同步组件将使用同步器提供的模板方法来实现自己的同步语义。
相关博客
AbstractQueuedSynchronizer同步队列详解
AbstractQueuedSynchronizer独占式同步状态获取与释放
AbstractQueuedSynchronizer共享式同步状态获取与释放
参考资料
方腾飞:《Java并发编程的艺术》