繁体   English   中英

可重入锁条件公平

[英]Reentrant lock condition fairness

我对ReentrantLockCondition感到困惑。 这是文档:

  • 等待线程以 FIFO 顺序发出信号。

  • 从等待方法返回的线程重新获取锁的顺序与最初获取锁的线程相同,在默认情况下未指定,但对于公平锁,优先考虑那些等待时间最长的线程。

根据最新的子弹,公平性带来了一个明确的信号锁定重新获取顺序。

但是第一个子弹的含义是什么等待线程以 FIFO 顺序发出信号 我认为在这种情况下,信号仅意味着“信号”,这意味着它以 FIFO 顺序“解除”线程,但唤醒时的实际重新获取顺序由公平性决定。

有相当多的员工与 cxq 相关联,HotSpot 内部的等待队列我不太了解(不幸的是)。


问题

等待线程以 FIFO 顺序发出信号是否意味着等待线程以它们被停放的相同顺序解除停放(即使锁本身是不公平的)?

由于在一般情况下存在 unpark-require 竞赛,公平性是否提供了必要的重新获取排序保证?

正如“fair”和“unfair”锁的内部存储差异中所解释的,“fair”和“unfair”之间的实际区别不是队列的组织,而是在不公平模式下,尝试获取锁的线程可能即使队列中已经有等待线程,也会成功。 这样的超车线程根本不会与队列交互。

Condition上调用其中一个await方法的线程必须已经拥有关联的锁并将释放它,以便另一个线程可以获取它,满足条件并调用signalsignalAll 所以线程必须自己入队,以便其他线程知道要向哪个线程发出信号。 调用signal时,从 FIFO 中取出等待条件最长时间的线程。

发出信号的线程可能未停放,但也有可能尚未停放。 在任何一种情况下,它都必须重新获取锁,并且这种重新获取受到锁的公平保证。 到线程调用signal时,它必须拥有锁。 因此,发出信号的线程不能立即成功。 当锁被释放时,多个线程之间可能会发生竞争。

但是一个条件的 FIFO 顺序的信号意味着当两个或多个线程在相同的条件上等待并且一个得到信号时,它将是等待时间最长的线程,并且其他线程都不能超过,即使对于不公平的锁也是如此。 只有当多个线程发出信号或其他线程,不等待条件时,才尝试获取锁,不公平锁的获取顺序是任意的。 此外,正如链接的答案所提到的, tryLock()即使在公平锁上也可能会超过。

阅读 ReentrantLock (Java 12) 的源码我们可以看到,与公平和不公平 ReentrantLock 的区别很小。 区别在于扩展 java.util.concurrent.locks.AbstractQueuedSynchronizer 的 class。 在一种情况下是 FairSync,在另一种情况下是 NonfairSync。 两者都在 ReentrantLock 中定义,唯一的区别是 FairSync 在方法 tryAcquire 中实现了另一项检查。 阅读代码似乎在非公平 ReentrantLock FIFO 的最佳条件下也受到尊重,但由于取消、超时或类似情况,这不能保证。 在公平的 ReentrantLock 中,获取锁之前的任何线程(如果从队列中取消驻留)重新检查是否有较旧的线程。 我不确定是否理解第二个问题,但请注意释放锁的线程已从队列中取消驻留线程。 此外,如果释放锁的线程将队列中的旧线程解锁,这不足以避免饥饿,因为第三个线程可能需要在退出线程解锁等待的线程之前同时获得锁。 在公平模式下,每次有新线程尝试获得锁时,都会检查所有等待的线程,并且此被授予者 FIFO 并避免饥饿。

等待线程的外部中断不会改变队列顺序。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM