Java AQS(AbstractQueuedSynchronizer)面经

简介

Java AQS(AbstractQueuedSynchronizer)是Java并发包中一个重要的基础类,用于实现锁和同步器的底层工具。AQS提供了一种用于构建锁和同步器的框架,可以方便地实现各种并发控制的机制。

AQS的基本原理

AQS的基本原理是通过一个FIFO(先进先出)的双向队列来管理线程的等待状态,并利用CAS(CompareAndSet)操作来实现原子性的状态更新。AQS维护了一个int类型的状态变量,通过状态的不同值来表示不同的线程状态。

AQS的主要方法包括:

  • acquire:获取锁/同步器的操作,如果获取失败则进入等待队列。
  • release:释放锁/同步器的操作,同时唤醒等待队列中的第一个线程。
  • tryAcquire:尝试获取锁/同步器的操作,如果获取成功则返回true,否则返回false。
  • tryRelease:尝试释放锁/同步器的操作,如果释放成功则返回true,否则返回false。

AQS的应用场景

AQS提供了一种灵活的框架,可以用于实现各种并发控制的机制。常见的应用场景包括:

  • 独占锁:通过实现tryAcquiretryRelease方法来实现独占锁的机制。
  • 共享锁:通过实现tryAcquireSharedtryReleaseShared方法来实现共享锁的机制。
  • 同步器:通过实现tryAcquiretryRelease方法来实现一个自定义的同步器。

下面以一个简单的示例来演示AQS的应用场景。

示例:旅行图

我们以一个旅行图的例子来说明AQS的使用。假设有三个线程(A、B、C)要参加一次旅行,他们需要依次获取出行的权限。

import java.util.concurrent.locks.AbstractQueuedSynchronizer;

public class TravelPermission {
    private static class Sync extends AbstractQueuedSynchronizer {
        @Override
        protected boolean tryAcquire(int arg) {
            if (compareAndSetState(0, 1)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

        @Override
        protected boolean tryRelease(int arg) {
            if (getState() == 0) {
                throw new IllegalStateException("未获取到出行权限");
            }
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }

        @Override
        protected boolean isHeldExclusively() {
            return getState() == 1;
        }
    }

    private final Sync sync = new Sync();

    public void acquire() {
        sync.acquire(1);
    }

    public void release() {
        sync.release(1);
    }
}

上面的代码定义了一个TravelPermission类,它使用AQS实现了一个出行权限的控制机制。每个线程在出行前需要先获取出行权限,出行后需要释放出行权限。

```sequenceDiagram
A->>TravelPermission: acquire()
TravelPermission->>A: tryAcquire()
alt acquire成功
    A-->>TravelPermission: setExclusiveOwnerThread()
    TravelPermission-->>A: true
else acquire失败
    A-->>TravelPermission: false
end
A->>TravelPermission: release()
TravelPermission->>A: tryRelease()
alt release成功
    TravelPermission-->>A: true
else release失败
    TravelPermission-->>A: IllegalStateException
end
```markdown

```mermaid
journey
    A[线程A] --> B[线程B] --> C[线程C]

上面的示例代码中,tryAcquire方法尝试获取出行权限,如果成功则返回true,否则返回false。tryRelease方法用于释放出行权限。

在使用这个出行权限控制机制时,线程A、B、C依次调用acquire方法获取出行权限,并在出行结束后调用release方法释放出行权限。

public class Main {
    public static void main(String[] args) {
        TravelPermission travelPermission = new TravelPermission();