在 Java 面试中,CAS
(Compare and Swap,比较并交换)和AQS
(AbstractQueuedSynchronizer,抽象队列同步器)是经常被问到的重要知识点。下面为大家整理了一些常见的面试题及详细解析。
一、CAS 相关问题
1. 什么是 CAS 操作?
CAS 操作是一种硬件级别的原子操作,它包含三个操作数:内存位置(V)、预期原值(A)和新值(B)。当且仅当预期原值与内存位置的值相同时,才会将内存位置的值更新为新值。
例如:在多线程环境下,多个线程同时尝试修改一个共享变量,如果使用传统的加锁方式会导致性能下降,而 CAS 操作可以在不加锁的情况下实现高效的并发修改。
2. CAS 操作可能会带来哪些问题?
(1)ABA 问题:如果一个值从 A 变为 B,又变回 A,CAS 操作可能会误认为值没有被修改过。
(2)循环时间长开销大:如果 CAS 操作长时间不成功,会一直占用 CPU 资源进行循环尝试。
3. 如何解决 CAS 操作中的 ABA 问题?
可以通过添加版本号或者使用AtomicStampedReference
类来解决 ABA 问题。AtomicStampedReference
类在引用值的基础上增加了一个版本号,只有当引用值和版本号都相同时,CAS 操作才会成功。
4. 请举例说明在 Java 中如何使用AtomicInteger
类来实现 CAS 操作?
import java.util.concurrent.atomic.AtomicInteger;public class CASExample {public static void main(String[] args) {AtomicInteger atomicInteger = new AtomicInteger(0);// 尝试将值从 0 改为 1boolean success = atomicInteger.compareAndSet(0, 1);System.out.println("CAS 操作是否成功: " + success + ", 当前值: " + atomicInteger.get());}
}
二、AQS 相关问题
1. 什么是 AQS?
AQS 是 Java 并发包中众多同步组件的构建基础,它通过一个先进先出的等待队列来管理多线程的阻塞和唤醒。
2. AQS 是如何实现线程的阻塞和唤醒的?
AQS 使用LockSupport
类来实现线程的阻塞和唤醒。当线程获取锁失败时,会被封装成Node
节点加入到等待队列中,并通过LockSupport.park()
方法阻塞线程。当锁被释放时,会按照一定的策略唤醒等待队列中的线程。
3. 请举例说明如何基于 AQS 实现一个自定义的同步工具类?
import java.util.concurrent.locks.AbstractQueuedSynchronizer;public class CustomSync extends AbstractQueuedSynchronizer {@Overrideprotected boolean tryAcquire(int arg) {// 自定义获取锁的逻辑return false;}@Overrideprotected boolean tryRelease(int arg) {// 自定义释放锁的逻辑return false;}public static void main(String[] args) {CustomSync customSync = new CustomSync();// 使用自定义同步工具类的逻辑}
}
4. AQS 在 Java 中的哪些同步组件中得到了应用?
ReentrantLock
、CountDownLatch
、Semaphore
等同步组件都基于 AQS 实现。
以上就是关于 Java 面试中常见的 CAS 和 AQS 问题的整理,希望对大家的面试准备有所帮助。