Java后端高频面试问题:AQS和CAS

1.AQS

AQS:抽象同步队列AbstractQueuedSynchronizer

AQS是一个FIFO的双向队列,队列元素的类型为Node。AQS里面包括Node节点、state变量、ConditionObject内部类(条件变量)

一个锁对应一个AQS阻塞队列,对应多个条件变量,每个条件变量有自己的一个条件队列。

①Node节点

Node节点中的thread变量用来存放进入AQS队列里面的线程

shared变量用来标记该线程是获取共享资源时被阻塞挂起后放入AQS队列的

exclusive变量用来标记线程是获取独占资源时被挂起后放入AQS队列的

waitStatus变量记录当前线程的等待状态,waitStatus可以为cancelled(线程被取消了)、signal(线程需要被唤醒)、condition(线程在条件队列里面等待)、propagate(释放共享资源时需要通知其他节点)

②ConditionObject类

ConditionObject用来结合锁实现线程同步的。

ConditionObject是条件变量,每个条件变量对应一个条件队列(单向链表队列),其用来存放调用条件变量的await()方法后被阻塞的线程。

1.当一个获得锁的线程调用await()方法时(必须先调用锁的lock()方法获取锁),在内部会构造一个类型为Node.CONDITION的node节点,然后将该节点插入         条件队列末尾,之后当前线程会释放获取的锁(修改锁对应的state变量的值),并被阻塞挂起。

2.当另外一个线程调用ConditionObject条件变量的signal方法时(必须先调用锁的lock()方法获取锁),在内部会把条件队列里面队头的一个线程节点从条件队         列里面移除并放入AQS的阻塞队列里面,然后激活这个线程。


③state变量

private volatile int state; //共享变量,使⽤volatile修饰保证线程可⻅性

线程同步的关键是对状态值state进行操作,根据state是否属于一个线程,操作state的方式分为独占方式和共享方式。

1.在独占方式下,获取锁与释放锁的流程如下

当一个线程调用acquire()方法获取独占资源时,会首先使用tryAcquire()方法尝试获取资源,具体是设置状态变量state的值,成功则直接返回,失败则将当前线       程封装为Node.EXCLUSIVE的Node节点后插入到AQS的阻塞队列的尾部,并调用LockSupport.park(this)方法挂起自己。

当一个线程调用release()方法时会尝试使用tryRelease()操作释放资源,这里是设置状态变量state的值,然后调用LockSupport.unpark(thread)方法激活AQS队       列里面被阻塞的一个线程(thread)。被激活的线程则使用tryAcquire()尝试,看当前状态变量state的值是否能满足自己的需要,满足则该线程被激活,然后继续       向下运行,否则还是会被放入AQS队列并挂起。

2.在共享方式下,获取与释放资源的流程如下

当一个线程调用acquireShared()方法获取共享资源时,会首先使用tryAcquireShared()方法尝试获取资源,具体是设置状态变量state的值,成功则直接返回,       失败则将当前线程封装为Node.SHARED的Node节点后插入到AQS的阻塞队列的尾部,并调用LockSupport.park(this)方法挂起自己。

当一个线程调用releaseShared()方法时会尝试使用tryReleaseShared()操作释放资源,这里是设置状态变量state的值,然后调用LockSupport.unpark(thread)方法激活AQS队列里面被阻塞的一个线程(thread)。被激活的线程则使用tryAcquireShared()尝试获取资源,具体是查看当前状态变量state的值是否能满足自己的       需要,满足则该线程被激活,然后继续向下运行,否则还是会被放入AQS队列并挂起。



②CAS

CAS:CompareAndSwap (比较并替换)

CAS算法的过程是:它包含3个参数CAS(V,E,N),其中V表示要更新的变量,E表示预期值,N表示新值。

仅当V值等于E值时,才会将V的值设置为N,如果V值和E值不同,说明已经有其他线程做了更新,则当前线程什么都不做。最后CAS返回当前V的真实值。

在多个线程同时使用CAS操作一个变量时,只有一个会胜出,并成功更新,其余均会失败。失败的线程不会被挂起,仅是被告知失败,并允许再次尝试,当然也允许失败的线程放弃操作。

CAS怎么保证修改的值可见?volatile关键字

volatile 关键字的主要作⽤就是保证变量的可⻅性然后还有⼀个作⽤是防⽌指令重排序。

当修改volatile变量时,JMM会把线程对应的工作内存中的共享变量值刷新到主内存中。

当读取volatile变量时,JMM会把该线程对应的工作内存置为无效,线程从主内存中读取共享变量值。

ABA问题:在CAS操作中有个经典的ABA问题?解决方式?(版本号、时间戳)

假如线程①使用CAS修改初始值为A的变量X,那么线程①会首先去获取当前变量X的值(为A),然后使用CAS操作尝试修改X的值为B,如果使用CAS操作成功了,程序运行也不一定是正确的。

在线程①获取变量X的值A后,在执行CAS前,线程②使用CAS修改了X的值为B,然后又使用CAS修改了变量X的值为A。

所以,线程①执行CAS时X的值是A,但是这个A已经不是线程①获取时的A了,这就是ABA问题。


ABA问题的产生是因为变量的状态值产生了环形转换。

避免ABA问题:使用版本号或时间戳。给每个变量的状态值配备一个时间戳或者版本号。

#高频知识点汇总##Java##学习路径#
全部评论
Java后端面试高频问题:HashMap的底层原理:https://www.nowcoder.com/discuss/820700 Java后端面试高频问题:ConcurrentHashMap:https://www.nowcoder.com/discuss/820701 Java后端面试高频问题:BIO、NIO、AIO的区别:https://www.nowcoder.com/discuss/820703 Java后端高频面试问题:线程池:https://www.nowcoder.com/discuss/820704 Java后端高频面试问题:AQS和CAS:https://www.nowcoder.com/discuss/820706 Java后端高频面试问题:String相关:https://www.nowcoder.com/discuss/821375 Java后端高频面试问题:ArrayList相关:https://www.nowcoder.com/discuss/821377 Java后端高频面试问题:垃圾回收机制:https://www.nowcoder.com/discuss/822354 Java后端高频面试问题:MySQL索引和事务:https://www.nowcoder.com/discuss/823047
1
送花
回复
分享
发布于 2021-12-18 15:34
2022届秋招Java后端企业面试真题汇总①:https://www.nowcoder.com/discuss/817566 2022届秋招Java后端企业面试真题汇总②:https://www.nowcoder.com/discuss/818250 2022届秋招Java后端企业面试真题汇总③:https://www.nowcoder.com/discuss/818255
点赞
送花
回复
分享
发布于 2021-12-13 10:24
秋招专场
校招火热招聘中
官网直投
2022届秋招Java后端高频知识点汇总①--Java基础: https://www.nowcoder.com/discuss/819297 2022届秋招Java后端高频知识点汇总②--Java集合: https://www.nowcoder.com/discuss/819300 2022届秋招Java后端高频知识点汇总③--多线程: https://www.nowcoder.com/discuss/819302 2022届秋招Java后端高频知识点汇总④--Java中的锁: https://www.nowcoder.com/discuss/819304 2022届秋招Java后端高频知识点汇总⑤--JVM: https://www.nowcoder.com/discuss/819307 2022届秋招Java后端高频知识点汇总⑥--MySQL: https://www.nowcoder.com/discuss/819308 2022届秋招Java后端高频知识点汇总⑦--Redis: https://www.nowcoder.com/discuss/819310 2022届秋招Java后端高频知识点汇总⑧--计算机网络: https://www.nowcoder.com/discuss/819312 2022届秋招Java后端高频知识点汇总⑨--操作系统: https://www.nowcoder.com/discuss/819316 2022届秋招Java后端高频知识点汇总⑩--Spring: https://www.nowcoder.com/discuss/819319
点赞
送花
回复
分享
发布于 2021-12-13 10:24
需要Java面试资料的私信我
点赞
送花
回复
分享
发布于 2021-12-13 10:24
🎉恭喜牛友成功参与 【创作激励计划】高频知识点汇总专场,并通过审核! ------------------- 创作激励计划5大主题专场等你来写,最高可领取500元京东卡和500元实物奖品! 👉快来参加吧:https://www.nowcoder.com/discuss/804743
点赞
送花
回复
分享
发布于 2021-12-13 10:55
666
点赞
送花
回复
分享
发布于 2021-12-13 20:25
环形转变是什么意思?
点赞
送花
回复
分享
发布于 2021-12-24 12:03
不能哥t y t r t g g
点赞
送花
回复
分享
发布于 2023-01-14 13:57 浙江

相关推荐

下午面了美团,40Min面试,面试官人很好,也很有礼貌,面试体验非常舒服一开始聊了会儿天,聊了一些实验室的情况,最早实习时间和实习时长,然后他介绍了一下他自己那个部门(负责到店消费的,后端),还问了问开放性问题(平常面对困难怎么解决)。然后就照着简历问问题了:1.  先简单介绍一下自己的项目吧,有什么技术亮点,还有自己开发的时候遇到了什么困难2.  是不是练手项目3.  你说对SQL语句进行了优化,这个优化体现在哪些方面呢?(我主要是针对回表的减少进行的优化)4.  说一说mysql索引的优化方法吧,创建索引的原则5.  mysql有哪些锁,在项目中怎么加的?6.  SpringBoot的AOP原理7.  SpringBoot如何解决循环依赖(忘了,私密马赛)8.  Redis的数据类型(5种基本,3种特殊)9.  Redis有序集合的底层数据结构10. 如何用Redis实现分布式锁?那如何实现可重入锁呢?(我只答了setnx,但是可重入锁就不知道了)11. java的Synchronized和ReentrantLock的区别和联系?12. 讲讲java的AQS(AbstractQueuedSynchronizer)吧(私密马赛,不会)13. java的priorityQueue的底层原理14. java线程池的参数配置,还有他们的作用(说的不是很清楚,还得复习一下)15. Java ThreadLocal的原理,怎么解决内存泄漏的问题16. volatile关键字的作用,和Synchronized的区别17. HashMap的底层原理,描述一下往HashMap添加元素的过程,为什么长度是2的n次方,不是会发生什么18. java的基本数据类型最后让我做了一道sql题目(太久没写sql语句,join语法都用错了,还好最后还是过了):两个表,一个表是员工信息表,一个表是员工薪资表,找到薪资第二多的员工的详细信息,不能使用order by
点赞 评论 收藏
转发
8 60 评论
分享
牛客网
牛客企业服务