面试题答案
一键面试1. ArrayBlockingQueue 公平性模式实现机制
底层数据结构
ArrayBlockingQueue
基于数组实现,用于存储元素。数组的容量在创建队列时就已确定,无法动态扩展。- 它有两个指针
takeIndex
和putIndex
分别指向队头和队尾元素的位置,通过这两个指针来控制数据的入队和出队操作。
锁的实现
- 使用
ReentrantLock
作为锁机制,在公平性模式下创建ReentrantLock
时传入true
,即new ReentrantLock(true)
。 ReentrantLock
内部维护了一个Sync
抽象类,公平模式下使用FairSync
实现类。FairSync
在尝试获取锁时,会先检查同步队列中是否有等待时间更长的线程。如果有,则当前线程会进入同步队列等待,而不是直接尝试获取锁。
线程调度
- 等待线程被存储在
ReentrantLock
的同步队列(AbstractQueuedSynchronizer
的CLH
队列)中。 - 当锁可用时,
ReentrantLock
会按照线程在同步队列中的顺序,唤醒等待时间最长的线程。这个线程获取锁后,会从队列中移除,然后执行相应的入队或出队操作。
2. 公平性模式与非公平性模式的差异
底层数据结构
- 公平性和非公平性模式在底层数据结构上没有差异,都是基于数组和指针
takeIndex
、putIndex
来实现队列操作。
锁的实现
- 公平性模式:
ReentrantLock
使用FairSync
,获取锁时会先检查同步队列中是否有等待线程,若有则排队等待,按顺序获取锁。 - 非公平性模式:
ReentrantLock
使用NonfairSync
,获取锁时不会检查同步队列,直接尝试获取锁,即使队列中有等待线程,当前线程也可能优先获取锁。这种方式在高并发场景下可能导致某些线程长时间等待。
线程调度
- 公平性模式:线程严格按照在同步队列中的等待顺序获取锁,保证等待时间最长的线程优先获取资源。
- 非公平性模式:线程获取锁的顺序不确定,可能导致部分线程频繁获取锁,而其他线程等待时间过长,即所谓的 “饥饿” 现象。但在高并发下,非公平性模式因为减少了线程切换的开销,通常具有更高的吞吐量。