AQS之前都很模糊, 貌似开发过程中没有直接用到, 但是今天看到相关的理论,还是值得比较记录一下.
全称AbstractQueueSynchronizer抽象同步队列, 它是实现同步器的基础组件.
AQS是一个FIFO的双向队列,内部通过节点head和tail记录队首和队尾元素; prev记录当前节点的前驱节点,next记录当前节点的后继节点.
队列元素的类型为Node. 其中Node中的thread变量用来存放进入AQS队列里面的线程;
$Node节点:
SHARED: 标记该线程是获取共享资源时被阻塞挂起放入AQS队列的
EXCLUSIVE: 标记线程是获取独占资源时被挂起后放入AQS队列的
$waitStatus:记录当前线程等待状态
CANCELLED: 线程被取消了
SINGAL: 线程需要被唤醒
CONDITION: 线程在条件队列里面等待
PROPAGATE: 释放共享资源时需要通知其他节点
AQS维持了一个单一的状态信息state,可以通过getState,setState,compareAndSetState函数修改其值
对于ReenrantLock: state表示当前线程获取锁的可重入次数;
对于读写锁ReenrantReadWriteLock: state高16位表示读状态,也就是获取该锁的次数,低16位表示获取到写锁的线程的可重入次数;
对于Semphore来: state表示当前可用信号的个数;
对于CountDownlatch: state表示计数器当前值;
对于常见的上述四种锁实现大家自行查阅资料,如果这个原理明白,对上述四种锁实现应该理解的更透彻一些.
对于AQS来说,线程同步的关键是对状态值state进行操作,操作方式分为:独占方式和共享方式
比如独占锁ReentrantLock的实现,当一个线程获取到ReentrantLock的锁后,在AQS内部会首先使用CAS操作把这个state状态从1变为0,然后设置当前锁的持有者是当前线程,当该线程再次获取锁的时候发现它就是锁的持有者,则会把状态值从1变为2,也就是设置可重入次数,而当另外一个线程获取锁时发现自己并不是该锁的持有者就会被放入AQS阻塞队列然后挂起;
其他三种可以自行根据表现来理解.
预计下一篇内容: 独占方式以及共享方式下获取与释放资源的流程......
与君共勉....
网友评论