您的位置:首页 > 产品设计 > UI/UE

AbstractQueuedSynchronizer的介绍和原理分析

2016-08-03 15:24 316 查看
介绍:
提供了一个基于FIFO队列,可以用于构建锁或者其他同步装置的基础框架,
利用了一个int类型表示状态
使用方法是继承
子类通过继承并通过实现它的方法管理其状态{acquire 和release}的方法操纵状态
可以同时实现排它锁和共享锁模式

源码内使用:


使用类型:
独占类型
共享类型

内部属性:
队列保存线程引用和线程状态的容器, 将线程对同步器的一次访问,看作一个Node
Node(节点):



属性名称
说明
waitStatus1.SINGAL=-1 : 当前节点的后继节点需要运行,也就是unpark

2.CANCELLED=1:当前节点被取消

3.CONDIITION=-2 : 表示当前节点在等待Condition ,也就是Condition队列

4.propagate=-3:便是当前场景下后序的acquireshare能够得以执行

5.  0 :当前节点在sync队列中,等待获得锁 
nextWaiter 存储在Condition队列中的后继节点
同步队列,依托node构建 : 



同步器拥有syn队列的3个成员变量:
 头节点:head         尾节点:tail    状态 :state

构造函数:

 protected AbstractQueuedSynchronizer() { }

主要接口
acquire(intr arg)
该方法以排他的方式获取锁,对中断不敏感,完成synchronized语义。
源码:



tryacquire需要子类自己去实现,交给子类去实现{以ReentrantLock--fairLock为例子



未获取到,就生成waitor加入队列中



原理



release()
而release则表示将状态设置回去,也就是将资源释放,或者说将锁释放。

源码解析:





原理:
 该方法取出了当前节点的next引用,然后对其线程(Node)进行了唤醒,这时就只有一个或合理个数的线程被唤醒,被唤醒的线程继续进行对资源的获取与争夺。

private boolean doAcquireNanos(int arg, long nanosTimeout) throws InterruptedException
原理



public final void acquireShared(int arg)
调用该方法能够以共享获取状态,
逻辑:
尝试获取共享状态;
调用tryAcquireShared(arg)方法获得

获取失败加入syn队列
以共享锁模式加入队列

循环退出条件
当前节点的前驱节点是否为头节点且能够获取共享状态
与独占锁的退出机制一致

判断共享状态成功
将当前节点设为头节点,判断后继节点是否为共享模式
如果是,则唤醒该线程,对其进行唤醒操作,也就是同时激发多个线程并发的运行

获取状态失败 
使用LockSupport.park(this);将线程从调度器上摘下,进入休休眠状态



public final boolean releaseShared(int arg)
每次获取共享状态acquireShared都会操作状态,同样在共享锁释放的时候,也需要将状态释放。

总结:
这篇文章,我们从ReentrantLock出发,完整的分析了AQS独占功能的API及内部实现。
总的来说,思路其实并不复杂,还是使用的标志位+队列的方式,记录获取锁、竞争锁、释放锁等 一系列锁的状态,或许用更准确一点的描述的话,应该是使用的标志位+队列的方式,记录锁,竞争,释放等一系列独占的状态,因为站在AQS的层面state可以表示锁,也可以表示其他状态,它并不关心它的子类把它变成一个什么工具类,而只是提供了一套维护一个独占状态。
甚至,最准确的是AQS只是维护了一个状态,因为,别忘了,它还有一套共享状态的API,所以,AQS只是维护一个状态,一个控制各个线程何时可以访问的状态,它只对状态负责,而这个状态表示什么含义,由子类自己去定义。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  AQS 并发 同步