同一线程持续重复获取ReentrantLock时,其公平性如何保障?
ReentrantLock公平性与可重入性的兼容逻辑
这是个非常犀利的问题,刚好问到了ReentrantLock实现细节里容易混淆的点!咱们一步步拆解:
首先明确:公平锁的公平性是针对「锁竞争队列」的
ReentrantLock的公平性,本质是当锁处于可用状态时,分配给等待队列里最久的线程——注意,这里的前提是「线程正在参与锁的竞争」,也就是它还没持有锁,需要通过排队来获取。
可重入的本质:跳过竞争直接计数
当同一线程已经持有锁时,它再次调用lock()方法,ReentrantLock会直接做这两件事:
- 检查当前线程是不是锁的持有者(通过
getExclusiveOwnerThread()判断) - 如果是,直接把
holdCount(持有计数)加1,完全不涉及队列排队
这时候,其他等待的线程依然乖乖在队列里排着,根本不会被当前线程的重入行为插队。举个实际场景的例子:
- 线程A获取了公平锁,
holdCount=1 - 线程A再次调用
lock(),直接holdCount=2,全程没碰等待队列 - 线程B尝试获取锁,发现锁被持有,于是加入等待队列尾部
- 线程A执行完逻辑,连续调用两次
unlock(),holdCount降到0,锁被释放 - 公平锁机制唤醒等待队列的第一个线程——也就是线程B,完全符合「给最久等待线程分配锁」的规则
关于“无限获取锁”的误区
如果你担心的是「线程持有锁后无限重入,一直不释放」,那这其实不是公平性机制的问题:
- 不管公平还是非公平锁,只要持有锁的线程一直不释放(比如死循环里反复加锁却不解锁),其他线程都会陷入饥饿,但这是代码逻辑的bug,不是锁机制的锅
- 公平锁的职责是在锁可用时公平分配,而不是限制持有锁的线程合理的重入行为——毕竟重入本身就是为了避免同一线程自己死锁(比如递归调用里加锁)
总结一下:ReentrantLock的公平性和可重入性完全不冲突,公平性管的是「外部线程竞争锁」的场景,可重入管的是「持有锁的线程重复获取」的场景,两者的逻辑是分开的,不会互相干扰。
内容的提问来源于stack exchange,提问作者user2938723
相关产品推荐
相关产品推荐

