AQS

AQS是什么:AQS,是AbstractQueuedSynchronizer简称,直翻过来叫抽象的队列式同步器, 也可以称作队列同步器,它是java.util.concurrent.lock包下的一个工具类。直观来讲,AQS是Java提供的一个类,这个类是被Abstract修饰的,需要被子类继承。也就是说AQS是Java并发中用以解决多线程访问共享资源问题的同步机制的基本的框架(或者说是一种规范),为Java并发同步组件提供统一的底层支持。即,AQS是个为各个同步组件提供基本框架的一个抽象类。

AQS做了什么:提供解决同步问题的基础框架。AQS类内维护了一个volatile int型的变量state,用于表示同步状态(锁的释放与获取),同时提供了一些列诸如getstate、setstate、compareAndSetState的方法来管理该同步状态,这些方法是子类中需要重写的部分,并且,AQS提供了模板方法去调用这些重写的方法;另外,AQS用一个虚拟的CLH FIFO的双向队列来管理被阻塞的线程。

AQS的整体框架如下:

img

  • 有颜色的为方法,没颜色的为属性。

  • 框架共分为5层,从上到下,由浅入深,从AQS对外暴露的API到底层基础数据。

  • 当有自定义同步器接入时,只需重写第一层所需要的部分方法即可,不需要关注底层具体的实现流程。

    当自定义同步器进行加锁或者解锁操作时,先经过第一层的API进入AQS内部方法,然后经过第二层进行锁的获取,接着对于获取锁失败的流程,进入第三层和第四层的等待队列处理,而这些处理方式均依赖于第五层的基础数据提供层。

原理概述

AQS核心思想是:

  • 如果被请求的共享资源空闲,那么就将当前请求资源的线程设置为有效的工作线程,将共享资源设置为锁定状态;

  • 如果共享资源被占用,就需要一定的阻塞等待唤醒机制来保证锁分配。这个机制主要用的是CLH队列的变体实现的,将暂时获取不到锁的线程加入到队列中。

CLH:Craig、Landin and Hagersten队列,是单向链表,AQS中的队列是CLH变体的虚拟双向队列(FIFO),AQS是通过将每条请求共享资源的线程封装成一个节点来实现锁的分配。

原理如下:

img

AOS使用一个Volatile修饰的int类型的成员变量来表示同步状态,通过内置的FIFO队列来完成资源获取的排队工作,通过CAS完成对State值得修改。