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.