简体   繁体   English

可重入锁条件公平

[英]Reentrant lock condition fairness

I have a confusion regarding the ReentrantLock 's Condition .我对ReentrantLockCondition感到困惑。 Here is the documentation:这是文档:

  • Waiting threads are signalled in FIFO order.等待线程以 FIFO 顺序发出信号。

  • The ordering of lock reacquisition for threads returning from waiting methods is the same as for threads initially acquiring the lock, which is in the default case not specified, but for fair locks favors those threads that have been waiting the longest.从等待方法返回的线程重新获取锁的顺序与最初获取锁的线程相同,在默认情况下未指定,但对于公平锁,优先考虑那些等待时间最长的线程。

According to the latest bullet the fairness brings a well-specified ordering of lock reaquisition on signalling.根据最新的子弹,公平性带来了一个明确的信号锁定重新获取顺序。

But what is the meaning of the first bullet Waiting threads are signalled in FIFO order ?但是第一个子弹的含义是什么等待线程以 FIFO 顺序发出信号 I presume in this case signalling means just "signalling" meaning that it "unparks" the thread in the order FIFO order, but the actual reaquiring order on wake up is governed by the fairness.我认为在这种情况下,信号仅意味着“信号”,这意味着它以 FIFO 顺序“解除”线程,但唤醒时的实际重新获取顺序由公平性决定。

There are pretty large amount of staff tied with cxq and wait queues internal to HotSpot which I don't understand well (unfortunately). 有相当多的员工与 cxq 相关联,HotSpot 内部的等待队列我不太了解(不幸的是)。


QUESTION :问题

Does Waiting threads are signalled in FIFO order mean that waiting threads are unparked in the same order they were parked (even though the lock itself is unfair)?等待线程以 FIFO 顺序发出信号是否意味着等待线程以它们被停放的相同顺序解除停放(即使锁本身是不公平的)?

Does fairness provides reaquisition ordering guarantees which is necessary since there is unpark-reaquire race in general case?由于在一般情况下存在 unpark-require 竞赛,公平性是否提供了必要的重新获取排序保证?

As explained in Difference in internal storing between 'fair' and 'unfair' lock , the actual difference between “fair” and “unfair” is not the organization of the queue, but that in unfair mode, a thread trying to acquire the lock might succeed even when there are already waiting threads in the queue.正如“fair”和“unfair”锁的内部存储差异中所解释的,“fair”和“unfair”之间的实际区别不是队列的组织,而是在不公平模式下,尝试获取锁的线程可能即使队列中已经有等待线程,也会成功。 Such an overtaking thread will not interact with the queue at all.这样的超车线程根本不会与队列交互。

A thread calling one of the await methods on a Condition must already own the associated lock and will release it so that another thread can acquire it, fulfill the condition and invoke signal or signalAll .Condition上调用其中一个await方法的线程必须已经拥有关联的锁并将释放它,以便另一个线程可以获取它,满足条件并调用signalsignalAll So the thread must enqueue itself, so that the other thread knows which thread to signal.所以线程必须自己入队,以便其他线程知道要向哪个线程发出信号。 When signal is invoked, the thread waiting the longest time for the condition is fetched from the FIFO.调用signal时,从 FIFO 中取出等待条件最长时间的线程。

The signalled thread may get unparked but it's also possible that it hasn't parked yet.发出信号的线程可能未停放,但也有可能尚未停放。 In either case, it must reacquire the lock and this reacquisition is subject to the lock's fairness guaranty.在任何一种情况下,它都必须重新获取锁,并且这种重新获取受到锁的公平保证。 By the time a thread calls signal it must own the lock.到线程调用signal时,它必须拥有锁。 Therefore, the signalled thread can't succeed immediately.因此,发出信号的线程不能立即成功。 When the lock is released, there might be a race between multiple threads.当锁被释放时,多个线程之间可能会发生竞争。

But the signalling in FIFO order for a condition implies that when two or more threads are waiting on the same condition and one gets signalled, it will be the longest waiting thread and none of the others can overtake, even for an unfair lock.但是一个条件的 FIFO 顺序的信号意味着当两个或多个线程在相同的条件上等待并且一个得到信号时,它将是等待时间最长的线程,并且其他线程都不能超过,即使对于不公平的锁也是如此。 Only when more than one thread is signalled or other threads, not waiting for the condition, try to acquire the lock, the acquisition order of an unfair lock is arbitrary.只有当多个线程发出信号或其他线程,不等待条件时,才尝试获取锁,不公平锁的获取顺序是任意的。 Also, as the linked answer mentions, tryLock() may overtake even on a fair lock.此外,正如链接的答案所提到的, tryLock()即使在公平锁上也可能会超过。

Reading the source code of ReentrantLock (Java 12) we can see that there is only a small difference from fair and not fair ReentrantLock.阅读 ReentrantLock (Java 12) 的源码我们可以看到,与公平和不公平 ReentrantLock 的区别很小。 The difference consists in the class that extends java.util.concurrent.locks.AbstractQueuedSynchronizer.区别在于扩展 java.util.concurrent.locks.AbstractQueuedSynchronizer 的 class。 In one case it is FairSync in the other is NonfairSync.在一种情况下是 FairSync,在另一种情况下是 NonfairSync。 Both are defined in ReentrantLock and the only difference is that FairSync implements one more check in the method tryAcquire.两者都在 ReentrantLock 中定义,唯一的区别是 FairSync 在方法 tryAcquire 中实现了另一项检查。 Reading the code seems that in optimal condition also in non-fair ReentrantLock FIFO is respected but this is not guaranteed due to cancellation, time-outs or similar.阅读代码似乎在非公平 ReentrantLock FIFO 的最佳条件下也受到尊重,但由于取消、超时或类似情况,这不能保证。 In fair ReentrantLock any thread before acquire the lock (also if unparked from the queue) re-check if there is older threads.在公平的 ReentrantLock 中,获取锁之前的任何线程(如果从队列中取消驻留)重新检查是否有较旧的线程。 I'm not sure to understand the second question but notice that a thread is unparked from the queue by the thread that release the lock.我不确定是否理解第二个问题,但请注意释放锁的线程已从队列中取消驻留线程。 Also if the thread that release the lock unpark the older thread in the queue, this is not enough to avoid starvation because a third thread can require the lock concurrently gaining it before the exiting thread unpark the waiting one.此外,如果释放锁的线程将队列中的旧线程解锁,这不足以避免饥饿,因为第三个线程可能需要在退出线程解锁等待的线程之前同时获得锁。 In fair mode there is a check of all thread waiting every time a new one try to gain the lock and this grantees FIFO and avoid starvation.在公平模式下,每次有新线程尝试获得锁时,都会检查所有等待的线程,并且此被授予者 FIFO 并避免饥饿。

External interrupts of waiting thread does not change the queue order.等待线程的外部中断不会改变队列顺序。

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

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