自学内容网 自学内容网

面试官:给我什么是AQS?

AQS简介

  • AQS(AbstractQueuedSynchronizer)是Java并发工具包中的一个核心类,用于构建锁和其他同步器。
  • AOS(AbstractOwnableSynchronizer)是AQS和AQLS的父类,表示持有者与锁之间的关系。
  • AQLS(AbstractQueuedLongSynchronizer)是AQS的扩展,使用long类型代替int类型来存储状态,适用于资源数量可能超过int范围的场景。

AQS的核心思想

  • AQS的核心思想是在多线程访问共享资源时,通过一个volatile变量state来标识资源的锁定状态。
  • 当资源空闲时,尝试获取资源的线程会被设置为有效工作线程,资源被锁定。
  • 未获取到资源的线程会被放入阻塞队列,等待资源释放。

AQS的数据结构

  1. state变量

    • 使用volatile修饰,展示当前临界资源的获锁情况。
    • 提供了获取和修改state的方法,这些方法都是final修饰的,不能被子类重写。
  2. CLH双向队列

    • CLH锁是一种自旋锁的改进,是一个虚拟的双向队列。
    • AQS将每条请求共享资源的线程封装成一个CLH队列锁的一个节点(Node)。

AQS的资源共享模式

  1. 独占模式(Exclusive)

    • 资源是独有的,每次只能一个线程获取,如ReentrantLock
    • 线程获取锁后,可以多次重入,每次重入state加1,释放时需要释放相同次数。
  2. 共享模式(Share)

    • 资源可同时被多个线程获取,如CountDownLatch
    • 通过CAS操作减少state值,当state为0时,唤醒等待的线程。

AQS的Node节点

  • Node节点存储线程的引用、前驱节点、后继节点等信息。
  • 节点状态包括:
    • CANCELLED:节点已被取消。
    • SIGNAL:后继节点等待当前节点唤醒。
    • CONDITION:当前线程阻塞在Condition。
    • PROPAGATE:共享模式下,前置节点唤醒后面节点后,唤醒操作无条件传播下去。
    • 0:中间状态,当前节点后面的节点已经唤醒,但当前节点线程还没有执行完成。

AQS的获取资源与释放资源

  1. 获取资源

    • 入口是acquire(int arg)方法,arg是要获取的资源个数。
    • 通过tryAcquire方法尝试获取锁资源,失败则将线程封装为Node节点,存入等待队列。
  2. 释放资源

    • 入口是release(int arg)方法。
    • 通过tryRelease方法尝试释放锁资源,成功后唤醒等待的线程。

AQS的实现细节

  • 获取资源

    • 使用acquireQueued方法从等待队列的head节点开始,循环向后尝试获取资源。
    • 获取失败则继续阻塞,头结点若获取资源成功,则将后继结点设置为头结点。
  • 释放资源

    • 通过unparkSuccessor方法唤醒等待的线程。
    • tryRelease方法需要子类实现,如在ReentrantLock中减少state值。

总结

  • AQS是一个强大的同步器框架,通过state变量和CLH队列实现资源的锁定和解锁。
  • 子类需要实现tryAcquiretryRelease方法来具体控制资源的获取和释放。

原文地址:https://blog.csdn.net/modelsetget/article/details/140734692

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!