interview
java-concurrency
说说AQS吧?

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

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

QA

Step 1

Q:: 说说 AQS 吧?

A:: AQS,全称为AbstractQueuedSynchronizer,是Java并发包中的一个基础框架,广泛用于实现同步器,比如ReentrantLock、CountDownLatch、Semaphore等。AQS 通过一个FIFO的等待队列来管理线程的同步,线程的状态和排队机制在AQS中非常重要。它提供了两种同步模式:独占模式和共享模式。独占模式下,只有一个线程可以获得锁,而在共享模式下,多个线程可以同时获得锁。AQS 主要通过CAS操作来实现状态的原子性更新,并通过内部的Node结构维护线程队列。在面试中问到AQS,考察的是候选人对Java并发基础设施的理解,尤其是锁和线程间协作的机制。

Step 2

Q:: AQS的工作原理是什么?

A:: AQS通过一个volatile类型的int变量state来表示同步状态,通过CAS操作确保状态的安全更新。AQS的核心是一个双向队列(FIFO),每个线程试图获取锁时,如果无法获取,将会被加入到队列的尾部并阻塞。AQS的主要操作包括acquire、release、acquireShared、releaseShared等,这些操作通过修改state的值和操作线程队列来控制线程的同步。

Step 3

Q:: AQS的独占模式与共享模式有什么区别?

A:: AQS 的独占模式允许只有一个线程获取资源,其他线程会被阻塞,直到当前线程释放资源。典型的例子是ReentrantLock。共享模式允许多个线程同时获取资源,例如Semaphore和CountDownLatch。区别在于,独占模式只允许一个线程持有锁,而共享模式下,多个线程可以同时访问共享资源。

Step 4

Q:: 如何自定义同步器,基于AQS?

A:: 要自定义同步器,首先需要继承AQS,并实现其模板方法如tryAcquire、tryRelease、tryAcquireShared和tryReleaseShared。这些方法需要根据具体的同步器逻辑来实现。然后,通过调用AQS提供的acquire、release等方法来实现线程的同步逻辑。举个例子,可以实现一个自定义的不可重入锁,重写tryAcquire方法,通过CAS操作将state从0改为1,表示锁被持有。

用途

AQS 是 Java 并发编程的基石,用于实现多种同步机制,比如锁、信号量、闩锁等。在实际生产环境下,使用并发工具可以极大地提升系统的性能和响应速度,尤其是在高并发的情况下,锁的实现和性能至关重要。了解AQS不仅能帮助开发者理解这些工具的底层原理,还能帮助他们在需要定制化同步器时更有信心。面试中问到AQS,主要是考察候选人对并发控制的理解以及处理复杂多线程场景的能力。\n

相关问题

🦆
ReentrantLock是如何基于AQS实现的?

ReentrantLock通过继承AQS来实现独占锁功能。ReentrantLock内部类Sync继承了AQS,并且实现了tryAcquire和tryRelease方法。ReentrantLock支持重入性,因此在tryAcquire方法中,线程可以多次获取锁,只要state递增,释放锁时递减。

🦆
CountDownLatch是如何实现的?

CountDownLatch 是基于AQS的共享模式实现的。其内部通过Sync类继承AQS,初始state值为计数器的初始值。每次调用countDown方法,state会减少1,当state为0时,所有等待的线程会被释放。

🦆
Semaphore的工作机制是什么?

Semaphore也是基于AQS的共享模式实现。它通过一个计数器来限制对资源的访问,计数器的值表示当前可用的资源数量。获取资源时,计数器减1,释放资源时,计数器加1。当计数器为0时,线程进入阻塞状态,等待资源释放。

🦆
Lock与synchronized有什么区别?

Lock是Java 5引入的,提供了比synchronized更灵活的锁机制。Lock可以通过显式获取和释放锁,更加灵活,可以中断等待的线程,尝试获取锁,以及超时获取锁。synchronized是Java的内置锁,使用简单,但灵活性不足。Lock一般用于需要更复杂的锁控制的场景,而synchronized适用于简单的锁机制。