大厂面试真题-AQS中节点的入队时机有哪些
在AQS(AbstractQueuedSynchronizer)中,节点的入队操作主要发生在竞争同步状态失败时。
时机一:
在模板方法 acquire() 中,如果调用 tryAcquire(arg) 尝试成功, acquire() 将直接返回,表
示已经抢到锁;如果不成功,则开始将线程加入等待队列。
这里分为三种场景:
1 )模板方法 acquire(arg) 通过 addWaiter(Node node, int args) 方法,尝试将该节点加入到同步队
列的队尾,在存在竞争的场景时一般会成功。当然,如果加入失败,或者同步队列为空,就开始调
用 enq(final Node node) 自旋入队。
2 ) enq() 方法通过 CAS 自旋将新节点插入队列尾部。具体来说,如果 AQS 的队列非空,新节点
入队的插入位置在队列的尾部,并且是通过 CAS 方式插入的,插入之后 AQS 的 tail 将指向新节点,
新节点作为尾节点
3 ) enq() 方法初始化 AQS 队列再执行 CAS 自旋。如果 AQS 的队列为空,新节点入队时首先进行
队列初始化, AQS 通过 CAS 方法创建队首节点,并且将 tail 指针指向队首节点。然后自旋,进入 CAS
自旋插入操作,直到插入成功,自旋才结束。
时机二:
Condition 等待队列上的节点被 signal() 唤醒,会通过 enq(final Node node) 自旋入队,插
入 AQS 的尾部。