🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] <br/> > ### 队列同步器 * 队列同步器`AbstractQueuedSynchronizer`(以下简称同步器),是用来构建锁或者其他同步组件的基础框架,它使用了一个`int`成员变量表示同步状态,通过内置的`FIFO`队列来完成资源获取线程的排队工作. * 锁是面向使用者的,它定义了使用者与锁交互的接口(比如可以允许两个线程并行访问),隐藏了实现细节;同步器面向的是锁的实现者,它简化了锁的实现方式,屏蔽了同步状态管理、线程的排队、等待与唤醒等底层操作。锁和同步器很好地隔离了使用者和实现者所需关注的领域。 * 同步器的设计是基于模板方法模式的,使用者需要继承同步器并重写指定的方法。 * `getState()`获取当前同步状态。 * `setState(int newState)`设置当前同步状态。 * `compareAndSetState(int expect,int update)`使用CAS设置当前状态,该方法能够保证状态设置的原子性 <br/> > ### 队列同步器的实现 * 同步器依赖内部的同步队列(一个FIFO双向队列)来完成同步状态的管理,当前线程获取同步状态失败时,同步器会将当前线程以及等待状态等信息构造成为一个节点(Node)并将其加入同步队列,同时会阻塞当前线程,当同步状态释放时,会把首节点中的线程唤醒,使其再次尝试获取同步状态。 ![](https://i.loli.net/2019/03/11/5c860c8d8a311.png) * 节点进入同步队列之后,就进入了一个自旋的过程,每个节点(或者说每个线程)都在自省地观察,当条件满足(自旋的判断前驱节点是否为首节点并且能够获取到同步状态,头结点释放同步状态之后才会会唤醒后继节点),就可以从这个自旋过程中退出,否则依旧留在这个自旋过程中(并会阻塞节点的线程)。 ![](https://i.loli.net/2019/03/11/5c860e73adb64.png) * 共享式获取与独占式获取最主要的区别在于同一时刻能否有多个线程同时获取到同步状态。 * 在共享式获取的自旋过程中,成功获取到同步状态并退出自旋的条件就是`tryAcquireShared(int arg)`方法返回值大于等于0。共享式获取也需要释放同步状态,通过调用`releaseShared(int arg)`方法可以释放同步状态,对于能够支持多个线程同时访问的并发组件(比如Semaphore),它和独占式主要区别在于`tryReleaseShared(int arg)`方法必须确保同步状态(或者资源数)线程安全释放,一般是通过循环和`CAS`来保证的,因为释放同步状态的操作会同时来自多个线程。 <br/> > ### 公平锁与非公平锁的区别 * 公平性锁每次都是从同步队列中的第一个节点获取到锁,而非公平性锁出现了一个线程连续获取锁的情况。 * 公平性锁保证了锁的获取按照FIFO原则,而代价是进行大量的线程切换。非公平性锁虽然可能造成线程“饥饿”,但极少的线程切换,保证了其更大的吞吐量。 <br/> > ### `Condition`的实现分析 * 每个`Condition`对象都包含着一个队列(以下称为等待队列),该队列是`Condition`对象实现等待/通知功能的关键。 * 一个`Condition`包含一个等待队列,`Condition`拥有首节点(firstWaiter)和尾节点(lastWaiter)。当前线程调用`Condition.await()`方法,将会以当前线程构造节点,并将节点从尾部加入等待队列。`Condition`拥有首尾节点的引用,而新增节点只需要将原有的尾节点`nextWaiter`指向它,并且更新尾节点即可。上述节点引用更新的过程并没有使用`CAS`保证,原因在于调用`await()`方法的线程必定是获取了锁的线程,也就是说该过程是由锁来保证线程安全的。 ![](https://i.loli.net/2019/03/11/5c86113725b67.png) * 在`Object`的监视器模型上,一个对象拥有一个同步队列和等待队列,而并发包中的`Lock`(更确切地说是同步器)拥有一个同步队列和多个等待队列。 * 等待,调用`Condition`的`await()`方法,会使当前线程进入等待队列并释放锁,同时线程状态变为等待状态。如下图: ![](https://i.loli.net/2019/03/11/5c8611f65835a.png) * 通知,调用`Condition`的`signal()`方法,将会唤醒在等待队列中等待时间最长的节点(首节点),在唤醒节点之前,会将节点移到同步队列中。如下图: ![](https://i.loli.net/2019/03/11/5c8612617d112.png)