更多面试资料请添加wx:suns45
———Java的AQS———
1、AQS的理解
-
AQS是一个锁框架,提供了扩展地方
-
当多个线程抢锁时,获取不到锁的线程,AQS会自动管理
-
AQS是同步队列+条件队列
-
AQS分为4个时机,获取锁,释放锁,条件队列的阻塞、条件队列的唤醒。
2、 多个线程通过锁请求共享资源,获取不到锁的线程怎么办?
-
尝试获得锁,获得锁了直接返回,获取不到锁的走到 2;
-
用 Node 封装当前线程,追加到同步队列的队尾,追加到队尾时,又有两步,如 3 和 4;
-
自旋 + CAS 保证前一个节点的状态置为 signal;
-
阻塞自己,使当前线程进入等待状态。
3、排它锁和共享锁
-
排它锁只会唤醒头节点,
-
共享锁还会唤醒头节点和后续节点。
4、排它锁和共享锁的区别
-
排它锁的意思是同一时刻,只能有一个线程可以获得锁
-
共享锁可以允许多个线程获得同一个锁
5、同步队列
结构
-
双向链表,头是head,尾是tail
-
节点是Node,Node里面是prev和next属性
作用
阻塞获取不到锁的线程
大致过程
1.多个线程获取锁时,只有一个线程能获取锁,封装成node加入到同步队列当中
2.当有锁释放时,同步队列释放头节点。
6、进出同步队列的时机
- 进队列
1.多个线程获取锁时,获取不到锁的线程进入队列
2.唤醒条件队列,从条件队列移入同步队列
- 出队列
1.锁释放。
2.线程进入条件队列。
7、条件队列的作用
- 对同步队列的场景功能补充,比如队列满时,put线程,队列空时,take线程。
8、条件队列元素入队和出队的时机和过程
-
入队:执行await方法时,线程会释放锁,进入条件队列
-
出队:有线程signal/signalAll时。
9、描述一下条件队列中的节点转移到同步队列中去的时机和过程?
时机
- 当有线程执行 signal、signalAll 方法时,从条件队列的头节点开始,转移到同步队列中去
过程
-
找到条件队列的头节点将next设置为null,移除条件队列
-
将该节点追加到同步队列队尾
-
状态从Condition设置为0
-
节点的前一个节点设置为SIGNAL阻塞自己。
10、线程入条件队列时,为什么需要释放持有的锁?
- 原因很简单,如果当前线程不释放锁,一旦跑去条件队里中阻塞了,后续所有的线程都无法获得锁,正确的场景应该是:当前线程释放锁,到条件队列中去阻塞后,其他线程仍然可以获得当前锁。
11、我要自定义锁,大概的实现思路是什么样子的?
-
A类,在A类里面写一个内部B类继承AQS,实现tryAcquire和tryRelease两个方法,通过state是0判断可以获取锁,通过state递减为0可以判断释放锁
-
在A类中对外提供,lock和unlock方法
12、描述ReentrantLock两大特性:可重入性和公平性?底层分别如何实现的?
-
可重入性:对同一个资源重复加锁state会加1
-
公平性:按照线程入队列的顺序释放锁
-
底层:通过hasQueuedPredecessors,会判断当前线程节点是否是头结点的下一个节点。
13、如果一个线程需要等待一组线程全部执行完之后再继续执行,有什么好的办法么?是如何实现的?
-
CountDownLatch 就提供了这样的机制,比如一组线程有 5 个,只需要在初始化
-
CountDownLatch 时,给同步器的 state 赋值为 5,主线程执行 CountDownLatch.await ,子线程都执行 CountDownLatch.countDown 即可。
14、Atomic 原子操作类可以保证线程安全,如果操作的对象是自定义的类的话,要如何做呢?
Java 为这种情况提供了一个 API:AtomicReference,AtomicReference 类可操作的对象是个泛型,所以支持自定义类。
15、CountDownLatch和CyclicBarrier区别
CountDownLatch
-
CountDownLatch:有两个api,在创建的时候指定 数量,await,countDown
-
适用场景
- 当商品进行退货的时候,不使用Countdownlatch,需要遍历退货,返回给前端结果
- 使用Countdownlatch,可以并发执行退货,返回给前端结果
-
CountDownLatch是什么?
- 一个线程(或者多个), 等待另外N个线程完成某个事情之后才能执行
CyclicBarrier
-
CyclicBarrier:
- 只有1个await的api 在创建的时候指定 数量,等待指定数量的线程执行完成之后才可以去执行后面的逻辑。
-
是什么?
-
N个线程,他们之间任何一个没有完成,所有的线程都必须等待
-
每个线程代表一个跑步运动员,当运动员都准备好后,才一起出发,只要有一个人没有准备好,大家都等待.
-
CountDownLatch和CyclicBarrier区别
-
重用区别
-
CyclicBarrier 可重用
-
CountDownLatch 不可重用,计数值为 0 该 CountDownLatch 就不可再用了
-
-
概念区别
-
CountDownLatch 是计数器, 线程完成一个就记一个, 就像 报数一样, 只不过是递减的.
-
CyclicBarrier更像一个水闸, 线程执行就想水流, 在水闸处都会堵住, 等到水满(线程到齐)了, 才开始泄流.
-