MST

星途 面试题库

面试题:Java中AQS的队列结构是什么,它在同步机制中起到什么作用?

在Java的AQS(AbstractQueuedSynchronizer)中,队列结构是其实现同步的关键部分。请阐述该队列的具体数据结构(如双向链表等),以及它如何在多个线程竞争锁等同步场景下,对线程进行排队、唤醒等操作,从而实现同步控制。
33.6万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试
  1. 队列数据结构
    • AQS使用的队列是一个双向链表结构,节点类型为NodeNode类中包含前驱节点prev、后继节点next、线程thread以及等待状态waitStatus等属性。这种双向链表结构使得在队列中进行节点的添加、删除操作都比较高效,并且方便从队列头部或尾部进行遍历。
  2. 线程排队操作
    • 当一个线程尝试获取锁失败时,会创建一个新的Node节点,将当前线程封装在节点中。
    • 该节点会被插入到双向链表的尾部。具体过程如下:通过compareAndSetTail方法使用CAS(Compare - And - Swap)操作尝试将新节点设置为尾部节点,如果失败则说明有其他线程同时在进行相同操作,那么就通过循环不断尝试,直到成功。同时,新节点的前驱节点会设置为旧的尾部节点。
  3. 线程唤醒操作
    • 当持有锁的线程释放锁时,会唤醒队列头部的线程。
    • 首先获取队列头部节点(即等待时间最长的节点),判断该节点的线程是否需要唤醒(通过检查节点的waitStatus等状态)。
    • 如果需要唤醒,则通过LockSupport.unpark方法唤醒节点中的线程。被唤醒的线程会尝试重新获取锁,获取成功后会将自己设置为新的头部节点,原头部节点的后继节点成为新的头部节点,原头部节点的前驱和后继节点都设置为null,以便垃圾回收。如果获取锁失败,该线程会重新进入等待状态。

通过这样的队列结构和操作机制,AQS实现了多个线程竞争锁等同步场景下的同步控制,确保线程按照一定的顺序获取锁,避免了竞争条件和死锁等问题。