I have seen there are different ways a thread could get to blocked state. I'm interested to know what exactly happens after a thread is in blocked state. How does it get back to running state?
If its blocked by sleep(time) then i开发者_开发知识库t moves to the runnable queue after time milli secs. If its blocked on a I/O operation it gets into the runnable queue once that is done.
How does it get to the runnable queue when it is waiting on an objects lock? How does it know that the lock on the object its waiting for is now available? Can some one also explain the internals of how the blocked thread on I/O works?
Please correct me if my understanding on any of the above topics isn't right..
How does it get to the runnable queue when it is waiting on an objects lock?
If the thread is blocked due to trying to enter a synchronized
block, the thread is automatically marked as runnable when the other thread (holding the lock) releases the lock by exiting from a synchronized
block of the same object.
If the current thread is blocked due to a call to someObject.wait()
, the thread is "released" when another thread calls someObject.notify()
.
On the bytecode level it looks as follows:
[load some object, obj, onto the operand stack]
monitorenter // grab the lock
// do stuff
[load obj onto the operand stack again]
monitorexit // release the lock
If someone else already holds the lock of obj
, the thread will hang on monitorenter
until the other thread calls monitorexit
.
The exact details of how monitorenter
and monitorexit
should be implement is not specified by the JLS. That is, it is JVM/OS dependent.
For further details, refer to JLS Wait Sets and Notifications.
On a close-to-code level it looks like this:
Thread 1:
Object mutex = new Object();
....
synchronized(mutex) {
//lock to mutex is acquired.
mutex.wait(); //lock to mutex is released. Thread is waiting for somebody to call notify().
doSomething();
}
Thread 2:
synchronized(Thread1.mutex) {
//acquires the lock on mutex.
//Can be done only after mutex.wait() is called from Thread1
// and the lock is released
Thread1.mutex.notify(); // notifies Thread1 that it can be resumed.
}
In general you should keep in mind that Thread.sleep() holds the lock on the resources, but Thread.wait() releases the locks and can be notified by other Threads.
AFAIK JVM use native threads. So it is OS not JVM that manage thread schedule and context switching.
You can look at actual JVM source code. It's open.
精彩评论