目录
- 一、AQS 概述
- 1.1 什么是 AQS?
- 1.2 AQS 与 synchronized 区别:
- 1.3 AQS 常见的实现类:
- 二、AQS 的工作原理
- 2.1 state 的用途:
- 2.2 AQS 双向链表:
- 2.3 ConditionObject 双向队列:
- 2.4 总结:画图说明
- 三、AQS 资源同步
- 3.1 AQS 资源同步方式
- 3.2 自定义同步器
- 3.3 常见同步工具类
- 1)Semephore 信号量
- 2)CountDownLatch 计数器
- 3)CyclicBarrier 循环栅栏
一、AQS 概述
1.1 什么是 AQS?
AQS
就是 AbstractQueuedSynchronizer 抽象类 的简称,它其实就是 JUC 包下的一个基类。- JUC 下的很多内容都是基于 AQS 实现了部分功能,比如:
ReentrantLock
、ThreadPoolExecutor
、阻塞队列
、CountDownLatch
、Semaphore
、CyclicBarrier
等等都是基于 AQS 实现的。
1.2 AQS 与 synchronized 区别:
synchronized | AQS |
---|---|
关键字,C++ 语言实现 | Java 语言实现 |
悲观锁,自动释放锁 | 悲观锁,手动开启和关闭锁 |
锁竞争激烈,都是重量级锁,性能差 | 锁竞争激烈的情况下,提供了多种解决方案 |
1.3 AQS 常见的实现类:
- ReentrantLock:阻塞式锁
- Semaphore:信号量
- CountDownLatch:计数器
- CyclicBarrier:循环屏障
二、AQS 的工作原理
首先 AQS 中提供了一个由 volatile
修饰,并且采用 CAS 方式修改的 int 类型的 state 变量。
2.1 state 的用途:
- ReentrantLock 中,使用 state 属性来标记当前互斥锁是否有线程持有,如果没有线程持有的话 state 就是 0,如果有线程持有的话 state 是大于 0 的。
- ThreadPoolExecutor 中,worker 工作线程也是基于 state 变量来实现了一个锁的概念。
- CountDownLatch 中,将 state 变量作为一个计数器,CountDownLatch 会在构建时声明好总数是多少。这个总数会直接赋值给 state,每次执行 countDown() 方法的时候,就会对 state 执行 -1 的操作。
- Semaphore 中,也是基于 state 变量去记录现在有多少个资源,每个线程想要拿资源去操作时,也是对 state 进行 -1 的操作;当归还资源时,再执行 +1 操作。
由此可以看出,这个 state 变量是非常非常核心的一个属性。只要是用到了 AQS 基本上都用到了 state 属性。
2.2 AQS 双向链表:
除了 state 变量,AQS 中维护了一个 双向链表
,有 head,有 tail,并且每个节点都是 Node 对象。
Node 源码如下所示:
static final class Node {// 表示线程以共享的模式等待锁static final Node SHARED = new Node();// 表示线程以独占的模式等待锁static final Node EXCLUSIVE = null;// 状态声明// 为0,表示当一个Node被初始化的时候的默认值// 为1,表示线程获取锁的请求已经取消了static final int CANCELLED = 1;// 为-1,表示线程已经准备好了,就等资源释放了static final int SIGNAL = -1;// 为-2,表示节点在等待队列中,节点线程等待唤醒static final int CONDITION = -2;// 为-3,当前线程处在SHARED情况下,该字段才会使用(解决jdk1.5中的一个Bug)s