AQS(AbstractQueuedSynchronizer)详解

  • AQS(AbstractQueuedSynchronizer)详解是一个用来构建锁和同步器的框架,许多的经典的同步器都是基于AQS构建出来的,譬如CountDownLatchSemaphored。其内部使用同步队列帮我们解决了实现同步器时的一些细节问题,譬如何时阻塞线程,如何按照顺序唤醒线程。

1. 核心思想

  • AQS通过一个被volatile修饰的int类型的成员变量表示同步状态(共享资源),然后使用cas对这个同步状态进行修改,从而保证线程安全。
  • 如果被请求的共享资源空闲,则将当前的请求线程设置为有效的工作线程,然后将对应的共享资源设置为锁定状态。
  • 如果共享资源被占用,则通过CLH同步队列将暂时用不到的线程封装成一个节点加入到队列中,同时在适当的时候对其进行阻塞和唤醒。

2. 基于AQS实现的应用(目前接触到的)

  • lock
    • 区别于synchronozed的锁,同时还支持了更加的灵活丰富操作,譬如可定时的尝试获取锁(避免了死锁的发生)、可中断的获取锁。
  • CountDownLatch
    • 一个或一组操作等其他操作执行结束之后,继续执行。
  • Semaphore
    • 用于多个共享资源的互斥,或者用于控制并发数量

3、内部细节:

  • 目前理解是通过waitStatus来标志线程的阻塞、唤醒等状态,但是每个节点的waitStatus状态不是通过自身设置的,而是通过其后继节点设置的
  • 内部的同步队列采用的数据结构是双向链表,同时Head节点属于dummy节点,不存储信息,仅表示当前持有锁的线程,同时还会负责后续阻塞线程的唤醒
  • exclusiveOwnerThread变量,标志当前持有锁的线程,防止错误的释放锁,这种思想在Redis分布式锁中也有体现
  • state是用volatile修饰的int型变量,这样其除了能够实现独占锁之外,还能实现SemaphoreCountDownLatch这样的同步工具
  • 对外提供了使用protected修饰的方法tryAcquiretryRelease等,这样在实现的子类中,能够通过这些方法,实现一些我们自定义的内容,譬如锁的可重入,公平与非公平锁。

4. 基于ReentrantLock的独占式共享锁的整个流程