Reputation: 1398
Let's say I have 2 threads, t1 and t2, and a lock object, m. Thread t1 is in an infinite loop, where at each iteration, it grabs a lock on m, does some work, unlocks m and starts over immediately. During one iteration, t2 requests a lock on m but gets blocked by t1 and has to wait. Now, when t1 unlocks m, is it guaranteed that t2 will obtain the next lock on m? or can t1 sneak ahead of it at the next iteration?
Generally, is there a queue set up for waiting threads? If t1 has the lock, and all remaining threads also wanting that lock get blocked in the following order: t2, t3, ..., will the remaining threads continue execution in the order that they were blocked (e.g. t2 runs, then t3, etc.)?
(I briefly perused the java spec and couldn't find the answer. If it's in there, please let me know, and I will go back to read more carefully.)
Thanks! (First SO post, woohoo!)
Upvotes: 9
Views: 3043
Reputation: 12056
Yes, there is a queue and it can be fair or not. Fair queues are more expensive and non-fair are faster (who wins the CAS wins the lock). check java.util.concurrent.locks.AbstractQueuedSynchronizer for further info.
will the remaining threads continue execution in the order that they were blocked (e.g. t2 runs, then t3, etc.)?
The main issue is that they are executed concurrently/simultaneously, you can't truly define order for 2 events that are executed in the same time. But w/ fair (unrecommended due to extra costs) locks any thread that manages to enlist itself for the lock will get eventually get to own it.
Upvotes: 3
Reputation: 340763
You can guarantee order by using fair Semaphore. Standard built-in Java locks/monitors aren't fair a do not queue orders in a fair manner.
Semaphore sem = new Semaphore(1, true);
//usage:
sem.acquire();
try {
//holding a lock
//of course both threads share the same semaphore
} finally {
sem.release();
}
With locks theoretically T1 can take a lock in next iteration again after releasing it, despite the fact that T2 already waits for it. Unlikely, but possible.
Upvotes: 0
Reputation: 9399
No there is no guarantee for most purposes. You'll notice some of the java.util.concurrent abstractions offer the option of a "fair lock" - which does more or less guarantee each thread waiting on a lock will eventually be called (not a specific order). Without fairness, there is no guarantee. OTOH, fairness is EXTREMELY expensive. (See Java Concurrency In Practice for some benchmarks), and usually, probablistic likelihood is good enough.
Upvotes: 0
Reputation: 287885
No, there are no such guarantees. You can advise Java to be ReentrantLock objects to be fair, but that's advisory and does not guarantee any order.
In general, you cannot (without explicit synchronization to achieve it) guarantee such an order, because t2 could have been interrupted before it even acquired the thread, and it's solely up to the OS to decide which thread gets resumed when.
Upvotes: 0