java中AQS的方法结构
java中AQS的方法结构
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的源代码。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 牧马人的忧伤!
评论