What happens to a Thread that fails to acquire a lock (non-spin)? It goes to the BLOCKED state. How does it gets executed again?
Lock lck = new ReentrantLock();
lck.lock()
try
{
}
finally
{
lck.unlock();
}
What happens to a Thread that fails to acquire a lock (non-spin)? It goes to the BLOCKED state. How does it gets executed again?
Lock lck = new ReentrantLock();
lck.lock()
try
{
}
finally
{
lck.unlock();
}
The scheduler (or the underlying Lock implementation) is responsible for getting it running again. If the lock action was translated into a mutex call all the way into the kernel, the scheduler will not reschedule the thread until the mutex becomes available; then the OS scheduler will re-awaken the thread. Reading the wikipedia page on Context Switch and links from there might provide more insight into the detailed mechanisms involved. You can also look directly at the code for ReentrantLock
though that will eventually boil your question down to some combination of primitives including AbstractedQueuedSynchronizer
, various atomic operations, and maybe LockSupport.park()
and unpark()
. You might augment your question or ask a new one if you're specifically interested in kernel-level blocking/context switches or specifically how various Java primitives (e.g., j.u.c.Lock
or primitive object monitors) are implemented atop the kernel.
In practice, because this is costly, this may be optimized away by the JVM or lock implementation. For instance, the thread may actually spin for a bit to see if the lock is freed before actually blocking.
Note that a Java thread may report the state BLOCKED even if the underlying OS thread is not blocked, specifically in the adaptive spinning cases described in the performance whitepaper below.
There are some great resources out there to learn about concurrency control in Java. Leading the pantheon is Java Concurrency in Practice. Some interesting discussion of synchronization performance in HotSpot 6.0 in the Java SE 6 Performance Whitepaper and some related slides.
The thread holding the lock unlocks the lock and then the (or "a") blocked thread is woken up. If the thread holding the lock never releases the lock (perhaps because it's blocked on another resource) then you get deadlock. A non-spinning lock will typically use the wait()/notify() primitives or something similar such that the thread is notified when the lock again becomes available.