Java并发编程面试题2

一、AQS高频问题:

1.1 AQS是什么?

AQS就是一个抽象队列同步器,abstract queued sychronizer,本质就是一个抽象类。

AQS中有一个核心属性state,其次还有一个双向链表以及一个单项链表。

首先state是基于volatile修饰,再基于CAS修改,同时可以保证三大特性。(原子,可见,有序)

其次还提供了一个双向链表。有Node对象组成的双向链表。

最后在Condition内部类中,还提供了一个由Node对象组成的单向链表。

AQS是JUC下大量工具的基础类,很多工具都基于AQS实现的,比如lock锁,CountDownLatch,Semaphore,线程池等等都用到了AQS。


state是啥:state就是一个int类型的数值,同步状态,至于到底是什么状态,看子类实现。

condition和单向链表是啥:都知道sync内部提供了wait方法和notify方法的使用,lock锁也需要实现这种机制,lock锁就基于AQS内部的Condition实现了await和signal方法。(对标sync的wait和notify)


sync在线程持有锁时,执行wait方法,会将线程扔到WaitSet等待池中排队,等待唤醒

lcok在线程持有锁时,执行await方法,会将线程封装为Node对象,扔到Condition单向链表中,等待唤醒


Condition在做了什么:将持有锁的线程封装为Node扔到Condition单向链表,同时挂起线程。如果线程唤醒了,就将Condition中的Node扔到AQS的双向链表等待获取锁。

1.2 唤醒线程时,AQS为什么从后往前遍历?

如果线程没有获取到资源,就需要将线程封装为Node对象,安排到AQS的双向链表中排队,并且可能会挂起线程

如果在唤醒线程时,head节点的next是第一个要被唤醒的,如果head的next节点取消了,AQS的逻辑是从tail节点往前遍历,找到离head最近的有效节点?

想解释清楚这个问题,需要先了解,一个Node对象,是如何添加到双向链表中的。

基于addWaiter方法中,是先将当前Node的prev指向tail的节点,再将tail指向我自己,再让prev节点指向我

如下图,如果只执行到了2步骤,此时,Node加入到了AQS队列中,但是从prev节点往后,会找不到当前节点。

image.png

1.3 AQS为什么用双向链表,(为啥不用单向链表)?

因为AQS中,存在取消节点的操作,节点被取消后,需要从AQS的双向链表中断开连接。

还需要保证双向链表的完整性,

  • 需要将prev节点的next指针,指向next节点。
  • 需要将next节点的prev指针,指向prev节点。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值