剖析公平锁与非公平锁:ReentranLock 源码解读
2024-02-03 14:19:26
前言
在并发编程的世界中,锁扮演着至关重要的角色,保障着多线程访问共享资源的安全性。其中,公平锁和非公平锁是两种常见的锁机制,它们在特性和适用场景上存在着显著差异。本文将通过剖析 ReentranLock
源码,深入理解这两类锁的运作原理。
ReentranLock 简介
ReentranLock
是 Java 并发库中提供的一种可重入锁,它支持公平锁和非公平锁两种模式。可重入是指同一线程可以多次获取同一把锁。
公平锁
公平锁是一种遵循先进先出的原则,即线程获取锁的顺序与它们申请锁的顺序相同。这意味着,即使一个线程处于等待状态,也不会被一个后来申请锁的线程抢占。公平锁保证了线程获取锁的公平性,避免了饥饿现象的发生。
非公平锁
非公平锁不遵循先进先出的原则,后申请锁的线程有可能抢占先申请锁的线程。这提高了线程获取锁的效率,但同时也可能导致饥饿现象的发生。
源码剖析
###公平锁的实现
ReentranLock
的公平锁模式通过 FairSync
类实现。该类使用了一个等待队列来管理申请锁的线程。当一个线程申请锁时,如果锁已被其他线程持有,则该线程会被加入到等待队列的尾部。当锁释放后,等待队列中的第一个线程将获得锁。
private static class FairSync extends Sync {
final ReentrantLock owner;
private Thread firstWaiter;
private int firstWaiterHoldedCount;
}
###非公平锁的实现
ReentranLock
的非公平锁模式通过 NonfairSync
类实现。与公平锁不同,非公平锁不使用等待队列。当一个线程申请锁时,如果锁已被其他线程持有,则该线程将直接挂起。当锁释放后,任意一个等待的线程都有机会获取锁。
private static class NonfairSync extends Sync {
private static final long serialVersionUID = 7313932542150178844L;
}
适用场景
公平锁和非公平锁在不同的场景下有各自的适用性。
- 公平锁: 适用于需要保证线程获取锁公平性的场景,例如:数据库更新、资源分配等。
- 非公平锁: 适用于需要提高线程获取锁效率的场景,例如:读写锁的写锁、高并发场景等。
总结
公平锁和非公平锁是两种不同的锁机制,它们在特性和适用场景上存在着差异。通过剖析 ReentranLock
源码,我们深入理解了这两类锁的实现原理。在实际应用中,应根据具体场景选择合适的锁机制,以保障多线程编程的正确性和效率。