赞
踩
AQS全名AbstractQueuedSynchronizer,抽象的队列式的同步器,它定义了一套多线程访问共享资源的同步器框架,许多同步类都依赖于它,如ReentrantLock、CountDownLatch、Semaphore等
AQS主要为一个volatile的state和一个CLH队列组成。
AQS核心思想是,如果被请求的共享资源空闲,那么就将当前请求资源的线程设置为有效的工作线程,将共享资源设置为锁定状态;如果共享资源被占用,就需要一定的阻塞等待唤醒机制来保证锁分配。这个机制主要用的是CLH队列的变体实现的,将暂时获取不到锁的线程加入到队列中。
AQS主要通过state去控制线程对共享资源的访问,此处的state用volatile修饰,主要原因为让state在线程间可见。
不同的同步器继承AQS后,通过对部分方法的重写,对state值进行不同的处理,以实现对共享资源的不同竞争方式。竞争方式一般分为两种:独占(ReentrantLock)和共享(CountDownLatch、Semaphore)
getState:获取state当前值
setState:主要用于初始化时使用
compareAndSetState:主要用于对state进行更新时使用
① isHeldExclusively:(在Condition中使用)当前线程是否正在独占资源。Returns true if synchronization is held exclusively with respect to the current (calling)
- protected boolean isHeldExclusively() {
- throw new UnsupportedOperationException();
- }
② tryAcquire:独占方式。尝试获取资源,成功则返回true,失败则返回false。
- protected boolean tryAcquire(int arg) {
- throw new UnsupportedOperationException();
- }
③ tryRelease:独占方式。尝试释放资源,成功则返回true,失败则返回false。
- protected boolean tryRelease(int arg) {
- throw new UnsupportedOperationException();
- }
④ tryAcquireShared:共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源。
- protected int tryAcquireShared(int arg) {
- throw new UnsupportedOperationException();
- }
⑤ tryReleaseShared:共享方式。尝试释放资源,如果释放后允许唤醒后续等待结点返回true,否则返回false。
- protected boolean tryReleaseShared(int arg) {
- throw new UnsupportedOperationException();
- }
注:在AQS中已经实现了这些方法,在设计模式中称为“模板方法”,但它们会直接抛出异常,目的是让子类选择自己需要用的方法进行重写,而不必重写所有方法。
CLH是一个带有自旋锁的双向队列,能确保无饥饿性,通过FIFO实现线程对共享资源的访问。
2.1.1、节点中的属性:
Node是CLH中的节点,它维护了以下两个主要属性:
(1)节点状态waitStatus:
① CANCELLED(1):表示当前结点已取消调度。当timeout或被中断(响应中断的情况下),会触发变更为此状态,进入该状态后的结点将不会再变化。
② SIGNAL(-1):表示后继结点在等待当前结点唤醒。后继结点入队时,会将前继结点的状态更新为SIGNAL。
③ CONDITION(-2):表示结点等待在Condition上,当其他线程调用了Condition的signal()方法后,CONDITION状态的结点将从等待队列转移到同步队列中,等待获取同步锁。
④ PROPAGATE(-3):当前线程处在SHARED情况下,该字段才会使用,共享模式下,前继结点不仅会唤醒其后继结点,同时也可能会唤醒后继的后继结点。
⑤ 0:新结点的初始化状态。
注:
① 非负值表示该节点处于被取消状态,大多数代码不需要检查特定的值,只用判断符号即可。
② 对于普通节点,waitStatus一般初始化为0
③ 对于condition节点,waitStatus一般初始化为CONDITION(-2)
(2)thread:
节点中维护的线程
2.1.1、节点的两种模式:
① SHARED:共享模式
② EXCLUSIVE:独占模式
注:
tryAcquire为模板方法,需要子类进行重写。
若子类为公平锁,tryAcquire只会在共享资源空闲或当前线程为资源独占线程时,才会成功,否则会失败。
若子类为非公平锁,tryAcquire除了在共享资源空闲或当前线程为资源独占线程时,还会去尝试CAS修改state的值,若修改成功,则获取成功,否则失败。
① 尝试释放资源
② 唤醒后继节点
AQS主要通过state去控制线程对共享资源的访问,不同的同步器继承AQS后,通过对部分方法的重写,对state值进行不同的处理,以实现对共享资源的不同竞争方式。
当state=0时,代表资源处于空闲状态,线程可去竞争资源。
当state>0时,代表资源已经被某个线程占有,此时state的值由当前线程进行修改值,state的数值为该线程重入的次数,每重入一次state+1,每释放一次state-1,当state减到0时,资源完全释放。
state的值为CountDownLatch的计数器,当state>0时,调用countDownLatch.await的线程等待,每当有一个线程调用countDownLatch.countDown,state-1,当state减到0时,等待的线程被唤醒。
state的值表示剩余的信号量,每当有线程调用semaphore.acquire获取到信号量时,state-1,每当拿到信号量的线程调用semaphore.release时state+1。当state=0时,表示无剩余信号量,此时正在调用semaphore.acquire的线程等待,当有其它线程释放信号量时,会唤醒clh队列中下一个等待的线程去争抢信号量。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。