AQS是什么:
抽象的队列同步器,很多并发工具类的基类,提供了通用的模版方法与处理逻辑,子类只需要关注获取资源、释放资源逻辑就行
其它框架实现类:
LimitLatch、CountDownLatch2、ThreadPoolExecutor.Worker
独占锁处理流程:
#acquire:获取资源模版方法
-
#tryAcquire:子类实现各自获取资源逻辑,子类返回true则结束方法;
-
#addWaiter:将请求封装成Node,追加到同步队列尾部
- 将node上一个节点设置为尾节点,CAS设置队尾,并将前队尾下一个节点设置为当前node;
- #enq:CAS设置失败后,进入enq方法,自旋加CAS,进行上面的操作;
-
#acquireQueue:获取资源或被挂起
- 如果当前node节点是 head节点并且#tryAcquire获取成功,则返回,并且返回false
- #shouldParkAfterFailedAcquire:当获取失败后再挂起线程之前,先保证当前node节点的上一个节点状态为SIGNAL;
- #parkAndCheckInterrupt:通过LockSupport#park挂起线程,并且通过Thread#interrupted消除线程中断状态(防止未获取到资源,再次挂起时失效)
-
#selfInterrupt:上面方法返回true后,中断当前线程,恢复线程中断状态;
AQS队列与CLH区别:
- AQS是双向链表,CLH是单向
- AQS不会一直自旋上一个节点状态,在合适的时候就会挂起线程
条件队列:
- 阻塞队列就是通过这个实现的。比如:ArrayBlockQueue的notFull、notEmpty
- #await:执行#await从同步队列删除加入到条件队列中,并阻塞当前线程
- #signal:执行#signal后从条件队列删除,并加入到同步队列
node节点状态:
- cancelled:1,已取消,是个异常状态;
- 0:默认状态
- signal:-1,独占锁,释放完资源后唤醒下一个线程;
- condition:-2,表示当前节点在条件队列;
- propagate:-3,共享模式;