AQS-速看

113 阅读2分钟
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,共享模式;