interview
java-concurrency
说说 AQS 吧

Java 并发面试题, 说说 AQS 吧?

Java 并发面试题, 说说 AQS 吧?

QA

Step 1

Q:: 说说 AQS 吧?

A:: AQS (AbstractQueuedSynchronizer) 是 Java 并发包中用于构建锁和同步器的基础框架。它通过一个先进先出(FIFO)队列来管理线程的获取和释放。AQS 主要通过两种方式进行同步:独占模式(如 ReentrantLock)和共享模式(如 CountDownLatch)。在独占模式下,只有一个线程可以获取资源;而在共享模式下,多个线程可以同时获取资源。AQS 提供了丰富的 API 和灵活的扩展性,使得开发人员可以方便地实现自定义的同步器。

Step 2

Q:: AQS 的核心机制是什么?

A:: AQS 的核心机制包括以下几点: 1. State:一个 volatile 变量,用于表示当前的同步状态。 2. FIFO 队列:通过 Node 类实现,用于保存等待获取资源的线程。 3. CAS 操作:通过 compareAndSet 方法原子性地更新 state 变量,确保线程安全。 4. 自定义同步器:通过继承 AQS 并重写其模板方法(如 tryAcquire、tryRelease)来实现不同的同步策略。

Step 3

Q:: 如何使用 AQS 实现一个自定义锁?

A:: 实现一个自定义锁需要以下步骤: 1. 继承 AbstractQueuedSynchronizer 类。 2. 实现 tryAcquire 和 tryRelease 方法,用于定义获取和释放锁的逻辑。 3. 实现 lock 和 unlock 方法,调用 AQS 提供的 acquire 和 release 方法。 4. 可以根据需要实现 Condition 接口来支持条件变量。示例如下:

 
class CustomLock 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) {
    setExclusiveOwnerThread(null);
    setState(0);
    return true;
  }
  public void lock() { acquire(1); }
  public void unlock() { release(1); }
}
 

Step 4

Q:: AQS 支持的同步模式有哪些?

A:: AQS 支持两种同步模式: 1. 独占模式(Exclusive):在这种模式下,只有一个线程可以访问资源。例如 ReentrantLock 就是基于这种模式实现的。 2. 共享模式(Shared):在这种模式下,多个线程可以同时访问资源。例如 CountDownLatch、Semaphore 和 CyclicBarrier 就是基于这种模式实现的。

Step 5

Q:: AQS 的 Node 结构是什么样的?

A:: AQS 的 Node 结构是一个内部类,包含以下字段: 1. thread:当前节点代表的线程。 2. nextWaiter:指向下一个节点,形成一个队列。 3. waitStatus:表示节点的等待状态,如 SIGNAL、CANCELLED 等。 4. prev 和 next:用于构成双向链表,形成同步队列。Node 主要用于管理和控制线程的排队和唤醒。

用途

AQS 是 Java 并发编程中的核心组件之一,了解 AQS 有助于理解和实现高级同步器,如 ReentrantLock、CountDownLatch 等。在实际生产环境中,当需要自定义复杂的同步机制或优化现有的并发控制时,AQS 提供了灵活且高效的解决方案。\n

相关问题

🦆
什么是 ReentrantLock?与 synchronized 关键字相比有什么优势?

ReentrantLock 是基于 AQS 实现的可重入锁,相比 synchronized 关键字,ReentrantLock 提供了更多的功能和更好的性能。其优势包括: 1. 可中断的锁获取操作。 2. 可限时的锁获取操作。 3. 支持公平锁和非公平锁选择。 4. 提供更灵活的条件变量支持。

🦆
介绍一下 CountDownLatch 的原理和使用场景?

CountDownLatch 是一个基于 AQS 的同步工具类,允许一个或多个线程等待,直到其他线程完成一组操作。它的工作原理是通过一个计数器来控制线程的阻塞和释放。使用场景包括: 1. 确保某些线程在其他线程完成初始化工作之后再执行。 2. 实现并行计算中的分治任务,等待所有子任务完成后汇总结果。

🦆
Semaphore 是什么?它的使用场景是什么?

Semaphore 是基于 AQS 实现的计数信号量,用于控制同时访问特定资源的线程数量。它通过 acquire 和 release 方法来管理许可数量。使用场景包括: 1. 限制数据库连接池的连接数量。 2. 控制对某些资源的并发访问,如文件、网络连接等。

🦆
CyclicBarrier 的实现原理是什么?

CyclicBarrier 也是基于 AQS 实现的同步工具,允许一组线程相互等待,直到到达一个公共的屏障点。每当线程调用 await 方法时,计数器减一,直到计数器为零,所有线程被释放并继续执行。CyclicBarrier 的主要使用场景是分阶段任务的并发处理,如多线程计算的同步和协调。

🦆
介绍一下 Condition 接口及其实现原理?

Condition 接口用于在多线程环境中实现更复杂的等待/通知机制,通常与 ReentrantLock 一起使用。它提供了 await、signal 和 signalAll 方法,类似于 Object 类的 wait、notify 和 notifyAll 方法。Condition 的实现基于 AQS 的条件队列,通过独占锁和条件队列的配合,实现线程间的精准控制。