java中AQS的方法结构

img

AQS的方法结构

 如果我们理解了上一节的设计思路,我们大致就能知道AQS的主要数据结构了。

组件 数据结构
同步状态 volatile int state
阻塞 LockSupport类
队列 Node节点
条件队列 ConditionObject

 进而再来看下AQS的主要方法及其作用。

属性、方法 描述、作用
int getState() 获取当前同步状态
void setState(int newState) 设置当前同步状态
boolean compareAndSetState(int expect, int update) 通过CAS设置当前状态,此方法保证状态设置的原子性
boolean tryAcquire(int arg) 钩子方法,独占式获取同步状态,AQS没有具体实现,具体实现都在子类中,实现此方法需要查询当前同步状态并判断同步状态是否符合预期,然后再CAS设置同步状态
boolean tryRelease(int arg) 钩子方法,独占式释放同步状态,AQS没有具体实现,具体实现都在子类中,等待获取同步状态的线程将有机会获取同步状态
int tryAcquireShared(int arg) 钩子方法,共享式获取同步状态,AQS没有具体实现,具体实现都在子类中,返回大于等于0的值表示获取成功,反之失败
boolean tryReleaseShared(int arg) 钩子方法,共享式释放同步状态,AQS没有具体实现,具体实现都在子类中
boolean isHeldExclusively() 钩子方法,AQS没有具体实现,具体实现都在子类中,当前同步器是否在独占模式下被线程占用,一般该方法表示是否被当前线程所独占
void acquire(int arg) 模板方法,独占式获取同步状态,如果当前线程获取同步状态成功,则由该方法返回,否则会进入同步队列等待,此方法会调用子类重写的tryAcquire方法
void acquireInterruptibly(int arg) 模板方法,与acquire相同,但是此方法可以响应中断,当前线程未获取到同步状态而进入同步队列中,如果当前线程被中断,此方法会抛出InterruptedException并返回
boolean tryAcquireNanos(int arg, long nanosTimeout) 模板方法,在acquireInterruptibly基础上增加了超时限制,如果当前线程在超时时间内没有获取到同步状态,则会返回false,如果获取到了则会返回true
boolean release(int arg) 模板方法,独占式的释放同步状态,该方法会在释放同步状态后,将同步队列中的第一个节点包含的线程唤醒
void acquireShared(int arg) 模板方法,共享式的获取同步状态,如果当前系统未获取到同步状态,将会进入同步队列等待,与acquire的主要区别在于同一时刻可以有多个线程获取到同步状态
void acquireSharedInterruptibly(int arg) 模板方法,与acquireShared一致,但是可以响应中断
boolean tryAcquireSharedNanos(int arg, long nanosTimeout) 模板方法,在acquireSharedInterruptibly基础上增加了超时限制
boolean releaseShared(int arg) 模板方法,共享式的释放同步状态
Collection getQueuedThreads() 模板方法,获取等待在同步队列上的线程集合
Node int waitStatus 等待状态1、 CANCELLED,值为1,在同步队列中等待的线程等待超时或者被中断,需要从同步队列中取消等待,节点进入该状态后将不会变化;2、 SIGNAL,值为-1,后续节点的线程处于等待状态,而当前节点的线程如果释放了同步状态或者被取消,将会通知后续节点,使后续节点的线程得以运行;3、 CONDITION,值为-2,节点在条件队列中,节点线程等待在Condition上,当其他线程对Condition调用了signal()方法后,该节点将会从条件队列中转移到同步队列中,加入到对同步状态的获取中;4、 PROPAGATE,值为-3,表示下一次共享式同步状态获取将会无条件地传播下去
Node prev 前驱节点,当节点加入同步队列时被设置
Node next 后续节点
Thread thread 获取同步状态的线程
Node nextWaiter 条件队列中的后续节点,如果当前节点是共享的,那么这个字段将是一个SHARED变量,也就是说节点类型(独占和共享)和条件队列中的后续节点共用同一个字段
LockSupport void park() 阻塞当前线程,如果调用unpark方法或者当前线程被中断,才能从park方法返回
LockSupport void unpark(Thread thread) 唤醒处于阻塞状态的线程
ConditionObject Node firstWaiter 条件队列首节点
ConditionObject Node lastWaiter 条件队列尾节点
void await() 当前线程进入等待状态直到signal或中断,当前线程将进入运行状态且从await方法返回的情况,包括:其他线程调用该Condition的signal或者signalAll方法,且当前线程被选中唤醒;其他线程调用interrupt方法中断当前线程;如果当前线程从await方法返回表明该线程已经获取了Condition对象对应的锁
void awaitUninterruptibly() 和await方法类似,但是对中断不敏感
long awaitNanos(long nanosTimeout) 当前线程进入等待状态直到被signal、中断或者超时。返回值表示剩余的时间。
boolean awaitUntil(Date deadline) 当前线程进入等待状态直到被signal、中断或者某个时间。如果没有到指定时间就被通知,方法返回true,否则表示到了指定时间,返回false
void signal() 唤醒一个等待在Condition上的线程,该线程从等待方法返回前必须获得与Condition相关联的锁
void signalAll() 唤醒所有等待在Condition上的线程,能够从等待方法返回的线程必须获得与Condition相关联的锁

 看到这,我们对AQS的数据结构应该基本上有一个大致的认识,有了这个基本面的认识,我们就可以来看下AQS的源代码。