首页 🔴 Java

1. 问: 什么是AQS?

答: AQS 全称 AbstractQueuedSynchronizer (抽象的队列同步器), 是除了 Java 自带的 synchronized 关键字之外的锁机制


2. 问: AQS的两大重要组成部分?

答:

①. 状态变量 state

  • 互斥锁: 当 AQS 只实现为互斥锁的时候, 每次只要使用 CAS 将 state 的值从0变为1成功了就获取了锁, 可重入是通过不断把 state 更新加1实现的
  • 互斥锁+共享锁: 当 AQS 需要同时实现为互斥锁+共享锁的时候, 低16位存储互斥锁的状态, 高16位存储共享锁的状态, 主要用于实现读写锁

②. CHL 队列

AQS 维护了一个双端队列, 所有加了"锁"线程(除了正在执行的), 都将会进入到这个队列中等待被唤醒(互斥锁模式下)


3. 问: AQS 独占锁获取/释放锁的原理?

答:

  • 获取: 获取同步状态时, 调用 acquire 方法, 维护一个同步队列, 使用 tryAcquire 方法安全地获取线程同步状态, 获取失败的线程会被构造同步节点并通过 addWaiter 方法加入到同步队列的尾部, 在队列中自旋 之后调用 acquireQueued 方法使得该节点以死循环的方式获取同步状态, 如果获取不到则阻塞, 被阻塞线程的唤醒主要依靠前驱节点的出队或被中断实现, 移出队列或停止自旋的条件是前驱节点是头结点且成功获取了同步状态
  • 释放: 释放同步状态时, 同步器调用 tryRelease 方法释放同步状态, 然后调用 unparkSuccessor 方法唤醒头节点的后继节点, 使后继节点重新尝试获取同步状态

4. 问: 什么是哨兵节点?

答: CHL 队列的头节点并不以一号等待线程, 而是一个空的 Node 节点, 这个节点被称为"哨兵节点"


5. 问: waitStatus 是什么? 有什么作用?

答:
waitStatus 是 Node 节点中的一个成员变量, 表示当前Node结点的等待状态, 共有5种取值CANCELLED、SIGNAL、CONDITION、PROPAGATE、0

  • CANCELLED(1): 在同步队列中等待的线程等待超时或被中断, 需要从同步队列中取消该 Node 的结点, 即放弃获取锁了
  • SIGNAL(-1): 表示后继结点在等待当前结点唤醒, 说白了就是为了唤醒后继结点
  • CONDITION(-2): 表示结点等待在 Condition 上, 当其他线程调用了 Condition 的 signal() 方法后, CONDITION 状态的结点将从等待队列转移到同步队列中, 等待获取同步锁
  • PROPAGATE(-3): 共享模式下, 前继结点不仅会唤醒其后继结点, 同时也可能会唤醒后继的后继结点
  • 0: 新结点入队时的默认状态

注意: 负值表示结点处于有效等待状态, 而正值表示结点已被取消; 所以源码中很多地方用$>$0、$<$0来判断结点的状态是否正常




文章评论