AQS源码解析

AQS源码解析

AQS是Java里的一个同步工具类,全称为AbstractQueuedSynchronizer。它是JUC包中中实现锁和同步机制的基础。

​ 它可以被认为是一种框架或模板,用于实现多种同步器,比如ReentrantLockCountDownLatchSemaphoreReentrantReadWriteLock等。

作为本系列第一节, 我们先了解这些同步工具的共同的祖先(虽然实际上是聚合关系) ----AQS

在了解AQS之前, 我们要知道:

AQS本质上是一个队列,它是将等待锁或资源的线程排队,并在锁或资源可用时将其唤醒。

建立在这个基础上, 方便理解后序讲解

我们以平常最常用的ReentrantLock为例

ReentrantLock lock= new ReentrantLock();

// 第一次获取锁
lock.lock();

try {

// 同步代码块块

} finally {

// 第一次释放锁
lock.unlock();
}

我们点进lock()方法, 会发现调用的是sync.lock();

public void lock() {
sync.lock();
}

sync是什么呢? 这其实是ReentrantLock一个内部类Sync的实例

Sync:是提供AQS实现的工具,类似于适配器,提供了抽象的lock(),便于快速创建非公平锁。

Sync继承自AQS(AbstractQueuedSynchronizer), 事实上, 上述几乎每个同步工具都又一个Sync的实现子类, 而且均继承自AQS, 这下就明白为什么说 AQS是一种框架或模板, 如果你想定义一个同步工具, 也完全可以通过继承AQS这个抽象类来实现, 文末我们会给出一个通过AQS简单自定义的互斥锁

而这个内部类也引出了我们本篇讲解的重点 AQS

这是

import java.util.concurrent.locks.AbstractQueuedSynchronizer;

/**
* 互斥锁 Mutex 的实现类
*/
public class Mutex {
// 内部类 Sync 继承 AbstractQueuedSynchronizer
private static class Sync extends AbstractQueuedSynchronizer {

/**
* 尝试获取互斥锁
*
* @param arg 获取锁的参数
* @return 如果获取锁成功返回 true,否则返回 false
*/
@Override
protected boolean tryAcquire(int arg) {
if (compareAndSetState(0, 1)) { // 尝试将状态从 0 设置为 1,表示成功获取锁
setExclusiveOwnerThread(Thread.currentThread()); // 设置当前线程为独占线程
return true; // 获取锁成功
}
return false; // 获取锁失败
}

/**
* 尝试释放互斥锁
*
* @param arg 释放锁的参数
* @return 如果释放锁成功返回 true,否则返回 false
*/
@Override
protected boolean tryRelease(int arg) {
if (getState() == 0) { // 状态为 0 表示锁没有被持有
throw new IllegalMonitorStateException(); // 抛出异常
}
setExclusiveOwnerThread(null); // 将独占线程设置为 null
setState(0); // 释放锁,将状态设置为 0
return true; // 释放锁成功
}

/**
* 判断是否为独占线程持有互斥锁
*
* @return 如果当前线程独占持有锁返回 true,否则返回 false
*/
@Override
protected boolean isHeldExclusively() {
return getState() == 1; // 状态为 1,表示当前线程独占持有锁
}
}

private final Sync sync = new Sync();

/**
* 获取互斥锁
*/
public void lock() {
sync.acquire(1); // 获取锁,如果锁已被持有,则当前线程进入阻塞状态
}

/**
* 释放互斥锁
*/
public void unlock() {
sync.release(1); // 释放锁
}

/**
* 判断互斥锁是否被独占持有
*
* @return 如果锁被独占持有返回 true,否则返回 false
*/
public boolean isLocked() {
return sync.isHeldExclusively();
}
}

这是一个使用内部类和 AQS 实现的互斥锁(Mutex)类。

  • tryAcquire:尝试获取资源。如果当前状态为0(未锁定),那么设置为1(锁定),并设 置当前线程为独占资源的线程。
  • tryRelease:尝试释放资源。设置状态为0并清除持有资源的线程。
  • isHeldExclusively:判断当前资源是否被独占。