Java并发-AQS和ReentrantLock
Java并发-AQS和ReentrantLock
xukunAQS与ReentrantLock
什么是AQS?
简单来说AQS就是起到了一个抽象、封装的作用,将一些排队、入队、加锁、中断等方法提供处出来,便于其他相关的JUC锁使用,具体加锁时机、入队时机等都需要实现类自己控制。
常见的实现类有ReentrantLock
、CountDownLatch
、Semaphore
等等。
AQS的核心机制
- 状态(State):AQS通过一个
volatile
类型的整数state
来表示同步状态。
子类通过 getState()、setState(int)和 compareAndSetState(int, int)方法来检查和修改该状态
状态可以表示多种含义,例如在 ReentrantLock 中,状态表示锁的重入次数;在 Semaphore 中,状态表示可用的许可数。
- 队列(Queue):
AQS
维护了一个FIFO
的等待队列,用于管理等待获取同步状态的线程。每个节点(Node)代表一个等待的线程,节点之间通过next
和prev
指针链接。
1 | static final class Node { |
当一个线程获取同步状态失败是,它会被添加到等待队列中,并自旋等待或被阻塞,直到前面的线程释放同步状态。
- 独占模式和共享模式:
独占模式:只有一个线程能获取同步状态,例如 ReentrantLock。
共享模式:多个线程可以同时获取同步状态,例如 Semaphore 和 ReadWriteLock。
ReentrantLock对AQS的使用
ReentrantLock 基于 AQS 实现的方式很简单,定义一个 Sync 继承 AQS 自定义 了tryAcquire、tryRelease、isHeldExclusively 等方法即可实现ReentrantLock和其他独占锁。所以说 AQS 把一切都封装的很好,基于 AQS 可以便于其他相关 JUC 锁的使用。
ReentrantLock
支持公平
和非公平
两种方式。
内部实现依靠一个 state
变量和两个等待队列:
同步队列AND等待队列
利用 CAS
修改 state
来争抢锁。争抢不到则入同步队列等待,同步队列是一个双向链表。
条件 condition
不满足时候则入等待队列等待,为单向链表。
是否是公平锁的区别在于: 线程获取锁时是加入到同步队列尾部还是直接利用 CAS
争抢锁。