1、什么是AQS?
AQS是抽象同步队列,基于CAS和LockSupport实现,通过资源状态state和AQS的同步队列实现线程抢占资源的管理。
2、获取资源
线程进来先获取资源,如果失败会重试一次,再次失败会将当前线程存放至同步队列,并调用park()阻塞当前线程。
3、释放资源
当线程释放资源的时候,会获取到同步队列中的头节点的next节点(因为头节点是当前线程),将next节点设置为头节点,并调用unpark()唤醒新头节点的线程去获取锁资源。
4、可重入锁
state的为2、3时,表示该资源被重入了。其原理为:当第一次获取资源失败,重试时会判断获取资源的线程是否为当前线程,如果是,则将state+1,返回ture。
5、为什么不唤醒所有阻塞的线程,而是只唤醒头节点的next节点?
在链表中遍历唤醒所有线程效率低O(N),而且根据链表中的存储顺序进行唤醒效率高O(1),也比较公平。
6、为什么同步队列头节点为空节点?
头节点表示获取到锁的线程记录,为了GC回收方便,所以所有头节点都变为空。已经在aqs类中已经记录绑定获取到锁的线程,所以head结点直接设置为null,防止浪费空间内存。
一、Lock底层实现
Lock底层基于CAS+AQS组合实现。先CAS自旋,自旋失败使用AQS。
CAS:CPU底层实现,采用预值比较交换的机制。
二、使用LockSupport操作线程挂起与唤醒
LockSupport底层基于UnSafe类,调用c代码,将线程变为阻塞/唤醒。
线程挂起:AQS先通过CAS将没有获取到锁的线程添加到阻塞队列,再通过LockSupport.park()将线程变成阻塞,类似Synchronized锁对象的wait()方法。
线程唤醒:AQS先获取需要唤醒的线程节点(头节点的next节点),然后通过LockSupport.unpark(Thread thread)将线程唤醒。
三、AQS介绍
AQS(AbstractQueuedSynchronizer):抽象同步队列类ÿ