详解JDK锁02:AQS
1. AQS简述
这一部分,我将从是什么、干什么、怎么用三个角度简单讲述一下AQS
1.1 是什么?
AQS全称为AbstractQueuedSynchronizer,中文名称为队列同步器。
拆分一下中文就可知,一定离不开 队列 与 同步 这两个概念,下面进一步讲解其作用。
1.2 干什么?
AQS是用来构建锁或者其他同步组件的基础框架。
学Java并发的话就重点关住于AQS是如何构建锁的,因为同步器是实现锁的关键!
- AQS用一个
int
成员变量来表示同步状态。通过修改同步状态,以此达到获取锁与释放锁的目的。
比如说一个线程获取到了锁,那么就相当于它此时获取到了同步状态。
一个线程执行完了它的任务,它去释放锁,就相当于释放同步状态。 - AQS通过内置的
FIFO队列
完成线程的排队工作。这一点其实并不难理解。当一个线程获取锁失败之后,可以选择陷入阻塞状态,也可以进行非阻塞地自旋重试;当有多个线程独占式地去获取锁时,只有一个线程可以获取成功,其它均会失败。那么应当如何管理这些竞争失败的锁呢?这便是队列的作用。
- 线程获取锁失败时,便进行入队列操作,成为队列的尾结点,进入等待状态
1.3 怎么用?
AQS的实现方式是继承:子类通过继承同步器并实现它的抽象方法来管理同步状态。
AQS支持独占式地获取同步状态与共享式地获取同步状态
其实AQS的精髓就在于它简化了锁的实现方式,我们不需要关心同步状态管理、线程排队、等待与唤醒等底层操作逻辑,我们只需要将精力放在锁的核心功能:加锁与解锁。
可以这样理解:
- 锁是面向使用者的,它定义了使用者与锁交互的接口,隐藏了实现细节
- AQS是面向锁的实现者,它定义了锁的实现者与同步器交互的接口,隐藏了实现细节
之后会写一个实战案例去用AQS实现一个锁。
2. AQS方法简述
下面三个方法是用于管理同步状态
getState()
:用于获取同步状态setState(int newState)
:用于设置同步状态compareAndSetState(int expect, int update)
:使用CAS设置同步状态,保证原子性
之前第一部分提到:AQS已经帮我们实现了队列的维护逻辑,我们实现锁时只需要重写获取锁的方法
tryAcquire(int arg)
:独占式地获取同步状态,返回值为布尔类型,true为获取成功,false为获取失败。tryRelease(int arg)
:独占式地释放同步状态,返回值为布尔类型,true为释放成功,false为释放失败。tryAcquireShared(int arg)
:共享式地获取同步状态,返回值为int类型。
- 返回0表示成功,且没有剩余资源
- 返回大于0的值表示成功,仍有剩余资源
- 返回负数代表获取失败
tryReleaseShared(int arg)
:共享式地释放同步状态,返回值为布尔类型。
- 如果释放后允许唤醒后续等待节点时,返回true;否则返回false
isHeldExclusively()
:当前同步器是否被线程独占
通过对于这些方法进行简单理解,便能初步体会到:
- 当同步状态state为0时,其他线程才有可能获取到同步状态,即获取到锁。
- 对于可重入锁,当线程独占锁之后,会将同步状态state进行自增。如果该线程一直重复地获取该锁,则state会一直累加;该线程去释放该锁时,必须将state自减到0,才算是完全释放成功。
3. AQS实战案例
通过使用AQS,简单地实现一个独占不可重入锁,也就是说该锁的state只有0与1两种状态。
重点关注继承自AQS的Sync内部类,这里面自定义了获取同步状态与释放同步状态的核心逻辑。
这个案例印证了这句话:AQS是面向锁的实现者,它定义了锁的实现者与同步器交互的接口,隐藏了实现细节
class ExclusiveLock implements Lock { private static class Sync extends AbstractQueuedSynchronizer { @Override protected boolean tryAcquire(int arg) { // 当通过CAS设置state为1时,代表加锁成功 if (compareAndSetState(0 ,1)) { setExclusiveOwnerThread(Thread.currentThread()); return true; } return false; } @Override protected boolean tryRelease(int arg) { // 释放锁时如果发现该锁已被释放,说明有异常 if (getState() == 0) throw new IllegalArgumentException(); setExclusiveOwnerThread(null); setState(0); return true; } // 当state==1时表示处于占用状态 @Override protected boolean isHeldExclusively() { return getState() == 1; } public Condition newCondition() { return new ConditionObject(); } } private final Sync sync = new Sync(); @Override public void lock() { sync.acquire(1); } @Override public void lockInterruptibly() throws InterruptedException { sync.acquireInterruptibly(1); } @Override public boolean tryLock() { return sync.tryAcquire(1); } @Override public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { return sync.tryAcquireNanos(1, unit.toNanos(time)); } @Override public void unlock() { sync.release(1); } @Override public Condition newCondition() { return sync.newCondition(); } }