面试题答案
一键面试公平和非公平策略对读写锁性能和线程调度的影响
- 公平策略
- 线程调度:公平策略下,线程按照请求锁的顺序依次获得锁。即当一个锁可用时,等待时间最长的线程会优先获取锁。这确保了每个线程都有机会获得锁,不会出现某些线程长时间等待的情况,符合“先来先服务”原则。
- 性能影响:由于需要维护等待线程的顺序,公平策略在高并发场景下会产生额外的开销。每次锁的竞争都需要检查等待队列,这增加了系统的复杂性和上下文切换的次数,从而可能导致整体性能下降。特别是在读操作频繁的场景下,因为读锁可以被多个线程同时持有,公平策略会使得读线程频繁地等待写线程释放锁,降低了读操作的并发性。
- 非公平策略
- 线程调度:非公平策略下,线程获取锁的顺序并不取决于等待时间的长短。当锁可用时,任何一个等待线程都有机会竞争到锁,而不管它等待了多久。这可能导致某些线程长时间等待,出现“饥饿”现象。
- 性能影响:非公平策略在高并发场景下通常能提供更好的性能。因为它不需要维护等待线程的顺序,减少了锁竞争时的开销。在写操作较少,读操作频繁的情况下,非公平策略允许读线程在写锁释放后立即获取锁,而不需要等待等待队列中的其他线程,提高了系统的整体吞吐量。
实现公平的读写锁
在Java中,ReentrantReadWriteLock
默认是非公平的,但可以通过构造函数来创建公平的读写锁。示例代码如下:
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class FairReadWriteLockExample {
private static final ReentrantReadWriteLock fairLock = new ReentrantReadWriteLock(true);
private static final ReentrantReadWriteLock.ReadLock fairReadLock = fairLock.readLock();
private static final ReentrantReadWriteLock.WriteLock fairWriteLock = fairLock.writeLock();
public static void main(String[] args) {
// 使用公平读写锁进行操作
fairWriteLock.lock();
try {
// 写操作
} finally {
fairWriteLock.unlock();
}
fairReadLock.lock();
try {
// 读操作
} finally {
fairReadLock.unlock();
}
}
}
在上述代码中,通过new ReentrantReadWriteLock(true)
构造函数创建了一个公平的读写锁。true
表示采用公平策略,此时线程将按照请求锁的顺序依次获得锁。在实际应用中,可以根据业务场景的需求选择合适的策略,以平衡性能和线程公平性。