更多面试资料请添加wx:suns45
AQS是一个锁框架,提供了扩展地方
当多个线程抢锁时,获取不到锁的线程,AQS会自动管理
AQS是同步队列+条件队列
AQS分为4个时机,获取锁,释放锁,条件队列的阻塞、条件队列的唤醒。
尝试获得锁,获得锁了直接返回,获取不到锁的走到 2;
用 Node 封装当前线程,追加到同步队列的队尾,追加到队尾时,又有两步,如 3 和 4;
自旋 + CAS 保证前一个节点的状态置为 signal;
阻塞自己,使当前线程进入等待状态。
排它锁只会唤醒头节点,
共享锁还会唤醒头节点和后续节点。
排它锁的意思是同一时刻,只能有一个线程可以获得锁
共享锁可以允许多个线程获得同一个锁
结构
双向链表,头是head,尾是tail
节点是Node,Node里面是prev和next属性
作用
阻塞获取不到锁的线程
大致过程
1.多个线程获取锁时,只有一个线程能获取锁,封装成node加入到同步队列当中
2.当有锁释放时,同步队列释放头节点。
1.多个线程获取锁时,获取不到锁的线程进入队列
2.唤醒条件队列,从条件队列移入同步队列
1.锁释放。
2.线程进入条件队列。
入队:执行await方法时,线程会释放锁,进入条件队列
出队:有线程signal/signalAll时。
时机
过程
找到条件队列的头节点将next设置为null,移除条件队列
将该节点追加到同步队列队尾
状态从Condition设置为0
节点的前一个节点设置为SIGNAL阻塞自己。
A类,在A类里面写一个内部B类继承AQS,实现tryAcquire和tryRelease两个方法,通过state是0判断可以获取锁,通过state递减为0可以判断释放锁
在A类中对外提供,lock和unlock方法
可重入性:对同一个资源重复加锁state会加1
公平性:按照线程入队列的顺序释放锁
底层:通过hasQueuedPredecessors,会判断当前线程节点是否是头结点的下一个节点。
CountDownLatch 就提供了这样的机制,比如一组线程有 5 个,只需要在初始化
CountDownLatch 时,给同步器的 state 赋值为 5,主线程执行 CountDownLatch.await ,子线程都执行 CountDownLatch.countDown 即可。
Java 为这种情况提供了一个 API:AtomicReference,AtomicReference 类可操作的对象是个泛型,所以支持自定义类。
CountDownLatch:有两个api,在创建的时候指定 数量,await,countDown
适用场景
CountDownLatch是什么?

CyclicBarrier:
是什么?
N个线程,他们之间任何一个没有完成,所有的线程都必须等待
每个线程代表一个跑步运动员,当运动员都准备好后,才一起出发,只要有一个人没有准备好,大家都等待.
重用区别
CyclicBarrier 可重用
CountDownLatch 不可重用,计数值为 0 该 CountDownLatch 就不可再用了
概念区别
CountDownLatch 是计数器, 线程完成一个就记一个, 就像 报数一样, 只不过是递减的.
CyclicBarrier更像一个水闸, 线程执行就想水流, 在水闸处都会堵住, 等到水满(线程到齐)了, 才开始泄流.