上一篇分析AQS的内部结构,其中有介绍AQS是什么,以及它的内部结构的组成,那么今天就来分析下前面说的内部结构在AQS中的具体作用(主要在具体实现中体现)。
二 AQS的接口和简单示例上篇有说到AQS是抽象类,而它的设计是基于模板方法模式的,也就是说:使用者需要继承同步器并重写指定的方法,随后将同步器组合在自定义同步组件的实现中,并调用其提供的模板方法。其中需要子类重写的方法与描述如下表:
方法名称 描述protected boolean tryAcquire(int arg)
尝试以独占模式获取。 此方法应查询对象的状态是否允许以独占模式获取它,如果是,则获取它。
实现该方法需要查询当前状态并判断同步状态是否预期,然后进行CAS设置同步状态。
protected boolean tryRelease(int arg)
尝试释放独占式的同步状态。
等待获取同步状态的线程将有机会获取同步状态。
protected int tryAcquireShared(int arg)
尝试以共享模式获取。 此方法应查询对象的状态是否允许在共享模式下获取它,如果是,则获取。
实现该方法需要查询当前状态并判断同步状态是否预期,然后进行CAS设置同步状态。
protected boolean tryReleaseShared(int arg)
尝试释放共享式的同步状态。
protected boolean isHeldExclusively() 表示当前同步器是否在独占模式下被线程占用。
在重写上面这些方法时,可能需要下面这三个方法(注意其中state是使用volatile关键字修饰的)
方法名 描述protected final int getState() 获取当前的同步状态
protected final void setState(int newState) 设置当前同步状态
protected final boolean compareAndSetState
(int expect, int update) 使用CAS设置当前状态,该方法能保证状态设置的原子性
其实前面这些都不需要关心,因为这些一般都是在自定义同步组件中实现。自定义同步组件除了重写第一个表格那些方法外,AQS还为其提供了一些公共方法(或者说模板方法),这些才是关键,也是重中之重。下面我先简单列出以及其方法描述,后面一一分析:
方法名称 描述public final void acquire(int arg)
独占式获取同步状态,忽略中断。
如果当前线程获取同步状态成功,则由该方法返回;否则将会进入同步队列等待(
即上篇说的Node节点队列)。
该方法将会调用重写的tryAcquire(int args)方法。
public final void
acquireInterruptibly(int arg)
与acquire(int args)方法一样,但是该方法响应中断(从方法名就大概知道意思了吧。)
当前线程未获取到同步状态而进入同步队列中,如果当前线程被中断,则该方法会抛出InterruptedException异常
public final boolean release(int arg)
独占式的释放同步状态, 该方法会在释放同步状态后将同步队列中第一个节点包含的线程唤醒。
该方法会调用tryRelease(int args)方法
public final void acquireShared(int arg)
共享式获取同步状态,忽略中断。
如果当前线程获取同步状态成功,则由该方法返回;否则将会进入同步队列等待
(即上篇说的Node节点队列)。
与独占式获取的主要区别是在同一时刻可以有多个线程获取到同步状态。