简体   繁体   中英

Reentrant lock condition fairness

I have a confusion regarding the ReentrantLock 's Condition . Here is the documentation:

  • Waiting threads are signalled in FIFO order.

  • 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 ? 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.

There are pretty large amount of staff tied with cxq and wait queues internal to HotSpot which I don't understand well (unfortunately).


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)?

Does fairness provides reaquisition ordering guarantees which is necessary since there is unpark-reaquire race in general case?

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. 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 . 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.

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. 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. 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.

Reading the source code of ReentrantLock (Java 12) we can see that there is only a small difference from fair and not fair ReentrantLock. The difference consists in the class that extends java.util.concurrent.locks.AbstractQueuedSynchronizer. In one case it is FairSync in the other is NonfairSync. Both are defined in ReentrantLock and the only difference is that FairSync implements one more check in the method 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. In fair ReentrantLock any thread before acquire the lock (also if unparked from the queue) re-check if there is older threads. 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.

External interrupts of waiting thread does not change the queue order.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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